Delphi/Firemonkey Change iOS screen rotation at runtime
Ok this rotation had me digging deep into the iOS API to figure out how iOS manages orientation.
Because you can not fake a rotation or force a device certain device orientation in iOS in iOS you have quite a few orientations to consider
- Device Orientation
- Statusbar orientation
- UIViewcontroller orientation
The device orientation can not be forced or altered this will always show the orientation your device is in now.
The statusbar orientation however has always had the setStatusBarOrientation
procedure you could call and spesify the orientation you wanted, but this was marked as deprecated, and thus was not working, but I didn't get a external exception when I called the function, which ment that it was still there, it just wasn't working.
then I read this :
The setStatusBarOrientation:animated: method is not deprecated outright. It now works only if the supportedInterfaceOrientations method of the top-most full-screen view controller returns 0
I then decided to try this
Application.FormFactor.Orientations := []; //the supportedInterfaceOrientations returns 0
App := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);
win := TUIWindow.Wrap(App.windows.objectAtIndex(0));
App.setStatusBarOrientation(UIInterfaceOrientationLandscapeLeft);
And it works the statusbar orientation changes, but like mentioned above, this protocol is deprecated so at some stage it can/will fall away and this will no longer work.
but this only changed the rotation of the statusbar and all alertviews etc, but the actual content within the rootviewcontroller is still in the Portrait in my case of wanting to change to landscape.
I then tought if I would in Delphi would go to Application->Orientation-> Enable custom rotation and say landscape only then the App will only display in landscape, and it does perfectly because when the form is created and then rootViewcontroller is made the supportedInterface orientations that is returned is only landscape and the Viewcontroller goes to Landscape.
Because when your device changes device orientation the orientation is evaluated against the Viewcontroller's supportedinterfaceorientations, if the orientation is not supported it is simply not rotated.
But when a new rootviewcontroller is assigned the GUI has to be updated to display in that Viewcontrollers supported orientations, with that in mind, here is my fix/hack to change the orientation of your App to a orientation you want.
TL;DR
Uses: iOSapi.UIKit;
procedure ChangeiOSorientation(toOrientation: UIInterfaceOrientation;
possibleOrientations: TScreenOrientations);
var
win : UIWindow;
App : UIApplication;
viewController : UIViewController;
oucon: UIViewController;
begin
Application.FormFactor.Orientations := []; //Change supported orientations
App := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);
win := TUIWindow.Wrap(App.windows.objectAtIndex(0)); //The first Windows is always the main Window
App.setStatusBarOrientation(toOrientation);
{After you have changed your statusbar orientation set the
Supported orientation/orientations to whatever you need}
Application.FormFactor.Orientations := possibleOrientations;
viewController := TUIViewController.Wrap(TUIViewController.alloc.init);//dummy ViewController
oucon := TUIViewController.Wrap(TUIViewController.alloc.init);
{Now we are creating a new Viewcontroller now when it is created
it will have to check what is the supported orientations}
oucon := win.rootViewController;//we store all our current content to the new ViewController
Win.setRootViewController(viewController);
Win.makeKeyAndVisible;// We display the Dummy viewcontroller
win.setRootViewController(oucon);
win.makeKeyAndVisible;
{And now we Display our original Content in a new Viewcontroller
with our new Supported orientations}
end;
All you have to do now is Call ChangeiOSorientation(toOrientation,possibleOrientations)
If you want it to go to Portrait but have landscape as a option
ChangeiOSorientation(UIInterfaceOrientationPortrait,[TScreenOrientation.Portrait,TScreenOrientation.Landscape,TScreenOrientation.InvertedLandscape]);
This is working on
- Delphi 10 Seattle
- iPhone 5 running iOS 9.0
- PA Server 17.0
- Xcode 7.1
- iPhoneOS 9.1 SDK
Screen orientation on iOS
This line:
if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXScreenService), Intf))
should be this instead:
if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXScreenService), &Intf))
Note the addition of the &
operator in the last parameter. This is even stated in the documentation:
Note: Please consider that you need to add & before Intf, as you can see in the code sample above.
Also, Intf
really should be declared to match the interface you are requesting, eg:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
_di_IFMXScreenService ScreenService;
if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXScreenService), &ScreenService))
{
TScreenOrientations Orientation;
Orientation << TScreenOrientation::Landscape;
ScreenService->SetScreenOrientation(Orientation);
}
}
How to prevent screen rotation with android development in delphi xe5 Firemonkey
Add FMX.Platform
to your uses
clause, and get rid of the redundant call to GetPlatformService()
:
uses
..., FMX.Platform;
procedure TLogin.FormCreate(Sender: TObject);
var
ScreenService: IFMXScreenService;
OrientSet: TScreenOrientations;
begin
if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then
begin
OrientSet := [TScreenOrientation.soLandscape];
ScreenService.SetScreenOrientation(OrientSet);
end;
end;
Firemonkey Listview & mobile screen orientation in Delphi 11
The Accessory
, Detail
and Text
items have an Align
property that can take values Center
, Leading
or Trailing
. They are recalculated and adjust their position with changes in the screen orientation.
Additionally some items have a separate property, TextAlign
, which sets the position for a text within the space of the Align
result.
Related Topics
Game Engine Collison Bitmask... Why 0X01 etc
Swift Unsafemutablepointer<Unmanaged<Cfstring>> Allocation and Print
How to Check Text Field Input at Real Time
Change Pin Image on Mkmapview in Swift
Nspredicate Filtered by Year Moth Day
Xcode5 Simulator: Unknown Option Character 'X' In: -Xlinker
iOS Uiwebview Crash in "Webthread"
Uipageviewcontroller Gesture Is Calling Viewcontrollerafter: But Doesn't Animate
How to Show Specific Language Keyboard When User Input Values in Uitextfield in iPhone App
Memory Leak with "Libbacktracerecording.Dylib" in React Native iOS Application
How to Change Device Orientation Programmatically in Swift
Adding Views. Storyboard VS. Programmatically
Urlsessiondelegate Function Not Being Called
How to Determine the Correct Altitude for an Mkmapcamera Focusing on an Mkpolygon
iOS Uimenucontroller Uimenuitem, How to Determine Item Selected with Generic Selector Method