I have a Qt / QML application on iOS. It is coded in C++ but I can include objective-c code in it.
I can change programmatically the orientation of the screen, which changes the orientation of the application, without changing the orienation of the iPad, and the user has to turn it when he notices the change of orientation of the screen.
I do that as I need to force the orientation depending on what I display on the application.
What I need to do now is to lock the automatic change of orientation (due to physical change) as I need it to be landscape sometimes and portrait other times.
To change the orientation programmatically, I found the above solution which works:
in my plist file, orientations must be allowed:
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
in my C++ code where I can insert objective-c:
void setScreenOrientation(bool inIsPortrait)
{
if(#available(iOS 16, *))
{
NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
UIWindowScene *scene = (UIWindowScene *)array[0];
UIInterfaceOrientationMask newOrientation;
if(inIsPortrait)
newOrientation = UIInterfaceOrientationMaskPortrait;
else
newOrientation = UIInterfaceOrientationMaskLandscapeRight;
UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:newOrientation];
[scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }];
}
else
{
//does not work on iOS 16, outputs following error:
//[Orientation] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)
NSNumber *newOrientation;
if(inIsPortrait)
newOrientation = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
else
newOrientation = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:newOrientation forKey:#"orientation"];
}
}
}
So with that, when I want to change the orientation from portrait to landscape or vice versa, I just call the function with the correct parameter.
The problem is that when I physically turn the iPad, the screen automatically changes its orientation due to the plist file. So when I force to landscape, the user sees the change so turns its iPad, but if he turns back to portrait, the automatic change will put back the screen to portrait, without calling my function of course.
I can't remove the orientations from the plist file as they are required if I want to change it programmatically.
But I would like to lock the screen in the selected orientation at the end of the function, and of course, unlock it at the beginning, so that physically turn the iPad won't change the screen orientation.
I found solutions with the function "shouldAutorotate" but it has to be overwritten and called in viewDidLoad or supportedInterfaceOrientationsForWindow which are specific to an objective-c implementation and architecture.
I found : Lock orientation with native Objective-C code from Qt
but I can't do that in my code as I don't have any ViewController, ... it's a Qt / QML application.
I would like to have something that I can call in my function, something to change the supported orientations, so modify "supportedInterfaceOrientationsForWindow" by calling it directly in a function. Something like:
[[UIApplication ???] supportedInterfaceOrientationsForWindow] = UIInterfaceOrientationMaskPortrait; //or UIInterfaceOrientationMaskLandscapeRight depending on what I need
or any other instructions but without having to override supportedInterfaceOrientationsForWindow.
Thanks
Related
i'm in need to force the orientation of the interface in landscape is the app runs in an iPad device.
I have found some code in stackoverflow that call
let value = UIInterfaceOrientation.landscapeRight.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
in a buttons and it should force the orientation of the device but i experienced no change in my app. the set to landscaperight does absolutely nothing.
How can i achieve the rotation?
I'm creating a iOS video camera app using Qt5.4.
For this I need to determine the current orientation of the device to rotate the video in the VideoOutput element.
As we can see there's a autoOrientation property but it doesn't work as I expect: if I keep switching the orientation it starts to have a weird behaviour i.e. setting the wrong orientation.
Then I tried to apply the rotation based on the Screen.primaryOrientation property:
Copying the function defined in this example, I've a created a similar version, which you can find here.
I call it every time width or height changes, like this:
onWidthChanged: { video.orientation = changeOrientation(); }
onHeightChanged: { video.orientation = changeOrientation(); }
However, it seems that the Inverted orientations are completely ignored, which is strange since they are listed in the documentation.
Anyone has any idea about why it's happening?
UPDATE:
I could isolate the problem when using autoOrientation, basically there's a menu on top of the VideoOutput, the menu is a RowLayout, it's visible only if the user clicks on the menu icon, and only if the user clicks on the menu icon the orientation gets messy.
However, in any situation the InvertedPortrait is not recognized.
I need to account for the different orientations a device can be in. Aka landscape, landscape flipped, portrait, or portrait flipped. My app is written in native C++ and is running on Windows 8.1 as a desktop app (cross platform is not a requirement in any way).
I know that I can determine if the device is in portrait or landscape using methods outlined by Microsoft here: http://msdn.microsoft.com/en-us/library/ms812142.aspx
However, there's no way to discern between landscape and landscape flipped (or portrait and portrait flipped).
I could get exactly what I need by checking the DisplayInformation.CurrentOrientation property but it's a WinRT API. Which means if I wanted to use it, my app would have to use CLR, which is a non-starter.
Also I'd really like to keep my app as a single executable and I don't think there's a clean way to do that and call managed APIs at the same time. But then again, I'm very inexperienced with native + managed code integration.
So, does anyone know of any way of figuring out display orientation using only native code in Windows?
I figured this out. It's actually a lot easier than I thought. EnumDisplaySettings() doesn't populate the dmDisplayOrientation field in the DEVMODE struct, but EnumDisplaySettingsEx() does. So it's actually really easy :)
There's a good example here.
Detect window SizeChanged in the XAML:
<Page x:Class="ClockCpp.MainPage"
Loaded="Page_Loaded"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ClockCpp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="black"
SizeChanged="Page_SizeChanged">
Then use is to toggle between portrait or landscape:
Boolean t46 = true;
void ClockCpp::MainPage::Page_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
{
if (t46 == true)
{
t46 = false; // portrait
timetext->FontSize = 120; // 2/3 of 180
Othercontrols->Visibility = Windows::UI::Xaml::Visibility::Visible;
}
else
{
t46 = true; // landscape
timetext->FontSize = 180;
Othercontrols->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
}
You could also compare the screen height and width. If the width value was more higher then it's landscape and vice versa..
#include <windows.h>
int theScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
int theScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN);
if (theScreenWidth > theScreenHeight)
MessageBox(NULL,"Run in landscape.","Landscape",MB_OK);
else
MessageBox(NULL,"Run in portrait.","Portrait",MB_OK);
The app is set up for only landscape.
In Project->target->Summary->Supported Interface Orientations, I enabled the 2 landscape icons (both left and right).
And in AppDelegate.m, the below code is written:
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
When the app is running on the device, the view showed at the beginning after the default cocos2d icon, all the positions are wrong which were all moved to the right-down side. When I rotate the screen, everything goes right, all in right position.
What's wrong?
I also tried the method below:
I disable all the icons in In Project->target->Summary->Supported Interface Orientations.
The code in AppDelegate still in use.
Then the view at the very beginning is ok but the screen can be rotated to protrait.
....
Any one can help?
Also put these two for iOS6 orientation, in AppDelegate.
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
return UIInterfaceOrientationMaskLandscape;
}
Look at this question and answer once.
In my cocos2d application, inside the applicationDidFinishLaunching method for my app delegate, I set the orientation via [director setDeviceOrientation:kCCDeviceOrientationPortrait] because I really only want portrait. However, Apple rejected my app saying it must support upside down portrait as well.
I'm not certain how I detect this, though. Reading the currentDevice orientation seems to return an unknown orientation, so my questions are twofold:
1) How am I supposed to detect the orientation so I can properly set it to either portrait or upsidedown portrait (where it will stay for good).
2) I suspect I'll have an issue with the splash screen because it's loaded before I reach this point in the delegate. How can I properly detect the orientation so I can set the right splash screen?
I can only edit the codes to fix your first question.. i hope you are using .99.5..
in RootViewController.h, in the function
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
look for this line:
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
{
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
}
change to
return ( UIInterfaceOrientationIsPortrait( interfaceOrientation ) );