Delphi / Firemonkey在运行时更改iOS屏幕旋转

基本上所有我想实现的是,当一个用户在应用程序的某个部分根据需要更改屏幕旋转,我有这个Andriod的工作,我不明白为什么它不应该为iOS

procedure TForm1.Button1Click(Sender: TObject); var ScreenService: IFMXScreenService; OrientSet: TScreenOrientations; begin if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin OrientSet := [TScreenOrientation.soLandscape];//<- Break point set here and line is executed ScreenService.SetScreenOrientation(OrientSet); end; end; 

采取从这里: 如何防止与android开发在delphi xe5 Firemonkey屏幕旋转

ScreenService.SetScreenOrientation被执行并且不会引发exception,但方向不会改变,我也在Project> Options> Application> Orientation中设置了启用自定义方向 ,但是这也没有任何作用。

对我来说奇怪的是,如果不支持,那就不应该这样

 if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) 

返回false? 甚至没有进入开始

我添加了一个testingbutton来检查屏幕的方向后,我把它设置为只与景观

 if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin case ScreenService.GetScreenOrientation of TScreenOrientation.Portrait: ShowMessage('Portrait'); TScreenOrientation.Landscape: ShowMessage('landscape'); TScreenOrientation.InvertedPortrait: ShowMessage('Inverted-Portrait'); TScreenOrientation.InvertedLandscape: ShowMessage('Inverted-Landscape'); else ShowMessage('not set'); end; end; 

如果它在纵向设置为横向后,它仍然说肖像

更新1 :我也试过改变

 OrientSet := [TScreenOrientation.soLandscape] // <- Deprecated 

 OrientSet := [TScreenOrientation.Landscape] 

但行为仍然是一样的

好吧,这个轮换让我深入iOS API深入了解iOS如何pipe理方向。

因为你不能在iOS iOS中强制旋转或强制某个设备取向 ,所以你需要考虑很多方向

  • 设备方向
  • 状态栏方向
  • UIViewcontroller方向

设备方向不能被强制或改变,这将始终显示您的设备现在的方向。

然而,状态栏方向始终有setStatusBarOrientation过程,你可以调用,并spesify所需的方向,但这被标记为不推荐,因此不工作,但我没有得到一个外部的exception,当我调用该函数,哪它仍然在那里,它只是不工作。

那么我读这个:

setStatusBarOrientation:animated:方法不被弃用。 现在,只有在最顶级的全屏视图控制器的supportedInterfaceOrientations方法返回0时,它才能工作

然后我决定试试这个

 Application.FormFactor.Orientations := []; //the supportedInterfaceOrientations returns 0 App := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication); win := TUIWindow.Wrap(App.windows.objectAtIndex(0)); App.setStatusBarOrientation(UIInterfaceOrientationLandscapeLeft); 

它适用于状态栏方向的变化,但是像上面提到的那样,这个协议已经被弃用了,所以在某个阶段它可能会失败,这将不再起作用。

但是这只是改变了状态栏和所有alertviews等的旋转,但是在我想要改变为横向的情况下,rootviewcontroller中的实际内容仍然在肖像中。

然后,我会如果我会在delphi将转到应用程序 – >方向 – >启用自定义旋转和说风景只有那么应用程序将只显示在横向,并且它完美,因为当表单创build,然后rootViewcontroller被支持接口返回的方向只是风景,Viewcontroller转到风景。

因为当您的设备更改设备方向时,将根据Viewcontroller支持的界面方向评估方向,如果方向不受支持,则不会进行旋转。

但是,当一个新的rootview控制器被分配的GUI必须更新,以显示在Viewcontrollers支持的方向,考虑到这一点,这里是我的修复/黑客更改您的应用程序的方向,以您想要的方向。

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; 

你现在所要​​做的就是调用ChangeiOSorientation(toOrientation,possibleOrientations)

如果你想要它去肖像,但有风景作为一个选项

  ChangeiOSorientation(UIInterfaceOrientationPortrait,[TScreenOrientation.Portrait,TScreenOrientation.Landscape,TScreenOrientation.InvertedLandscape]); 

这是在努力

  • Delphi 10西雅图
  • 运行iOS 9.0的iPhone 5
  • PA服务器17.0
  • Xcode 7.1
  • iPhoneOS 9.1 SDK