Delphi / Firemonkey Modifier la rotation de l'écran iOS à l'exécution

fondamentalement tout ce que je veux réaliser est quand un user est dans une certaine partie de l'application pour changer la rotation de l'écran au besoin, j'ai ceci fonctionnant pour Andriod et je ne peux pas voir pourquoi cela ne devrait pas fonctionner pour 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; 

Tiré d'ici: Comment empêcher la rotation de l'écran avec le développement android dans Delphi xe5 Firemonkey

ScreenService.SetScreenOrientation est exécuté et ne triggers pas d'exception, mais l'orientation n'est pas modifiée. J'ai également activé l' option Activer l'orientation personnalisée dans Projet> Options> Application> Orientation, mais cela n'a également eu aucun effet.

Ce qui est étrange pour moi, c'est que si ce n'était pas supporté, cela ne devrait pas

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

Retourne faux? et même pas entrer le début

J'ai ajouté un button de test pour vérifier l'orientation de l'écran après je l'ai mis en paysage uniquement avec

 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; 

Et si c'était dans Portrait après l'avoir réglé sur Paysage, il dit toujours Portrait

Mise à jour 1 : J'ai aussi essayé de changer

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

à

 OrientSet := [TScreenOrientation.Landscape] 

mais le comportement est toujours le même

Ok, cette rotation m'a permis de creuser profondément dans l'API iOS pour comprendre comment iOS gère l'orientation.

Parce que vous ne pouvez pas simuler une rotation ou forcer un périphérique à l' orientation de l'appareil dans iOS dans iOS, vous avez quelques orientations à considérer

  • Orientation de l'appareil
  • Orientation de la barre d'état
  • Orientation UIViewcontroller

L'orientation de l'appareil ne peut pas être forcée ou modifiée, cela montrera toujours l'orientation de votre appareil maintenant.

L'orientation de la barre d'état a toujours eu la procédure setStatusBarOrientation vous pouviez appeler et spécifier l'orientation que vous vouliez, mais elle était marquée comme obsolète et ne fonctionnait donc pas, mais je n'ai pas reçu d'exception externe lorsque j'ai appelé la fonction, qu'il était toujours là, ça ne fonctionnait pas.

alors je lis ceci:

La méthode setStatusBarOrientation: animated: n'est pas complètement déconseillée. Il ne fonctionne maintenant que si la méthode supportedInterfaceOrientations du controller de vue plein écran le plus haut renvoie 0

J'ai alors décidé d'essayer ça

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

Et cela fonctionne les changements d'orientation de la barre d'état, mais comme mentionné ci-dessus, ce protocole est obsolète donc à un certain stade, il peut / va tomber et cela ne fonctionnera plus.

mais cela n'a changé que la rotation de la barre d'état et de toutes les alertes, etc., mais le contenu réel dans le rootviewcontroller est toujours dans le Portrait dans mon cas de vouloir changer de paysage.

Je me suis alors demandé si je devais dans Delphi aller à Application-> Orientation-> Activer la rotation personnalisée et dire paysage seulement alors l'application affichera seulement dans le paysage, et il le fait parfaitement parce que lorsque le formulaire est créé, rootViewcontroller devient l'interface supscope les orientations renvoyées sont uniquement en mode paysage et le Viewcontroller passe en mode Paysage.

Parce que lorsque votre périphérique change l'orientation du périphérique, l'orientation est évaluée par rapport aux orientations de l'interface sockets en charge par le Viewcontroller. Si l'orientation n'est pas prise en charge, elle n'est simplement pas pivotée.

Mais quand un nouveau rootviewcontroller est assigné, l'interface graphique doit être mise à jour pour s'afficher dans les orientations sockets en charge par Viewcontrollers, en gardant cela à l'esprit, voici ma solution pour modifier l'orientation de votre application selon l'orientation souhaitée.

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; 

Tout ce que vous avez à faire maintenant est Call ChangeiOSorientation(toOrientation,possibleOrientations)

Si vous voulez que ça passe à Portrait mais que vous ayez un paysage en option

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

Cela fonctionne sur

  • Delphi 10 Seattle
  • iPhone 5 fonctionnant sous iOS 9.0
  • Serveur PA 17.0
  • Xcode 7.1
  • iPhoneOS 9.1 SDK