Comment gérer différentes orientations dans iOS

AJOUT: Vous pouvez accéder à ce projet sur github ios6rotations


Désolé les gars pour poser la question sur la rotation de l'écran dans iOS 6, mais c'est vraiment une douleur dans le cul … et je ne peux toujours pas le comprendre complètement – pour une raison quelconque, il se comporte différemment dans certaines circonstances.

J'ai la hiérarchie de vues simple suivante dans mon application de test:

Ce que j'essaye de réaliser est – pour garder le controller bleu dans le paysage seulement et le rouge est seulement en portrait .

J'ai une sous-class de UINavigationController avec un tel code à l'intérieur:

@implementation CustomNavController - (BOOL)shouldAutorotate { return [[self.viewControllers lastObject] shouldAutorotate]; } - (NSUInteger)supportedInterfaceOrientations { return [[self.viewControllers lastObject] supportedInterfaceOrientations]; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation]; } @end 

Dans mon controller bleu, j'ai implémenté ceci:

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } 

Et dans le controller rouge ceci:

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } 

Maintenant, j'ai le comportement suivant:

  1. L'application a démarré dans le paysage (OK)
  2. Lorsque j'appuie sur le button, mon controller rouge enfonce aussi le paysage (ce n'est pas correct car il doit apparaître dans Portrait)
  3. Il pivote avec succès vers le portrait mais pas vers l'arrière pour le paysage
  4. Si je laisse le controller rouge en mode Portrait, mon controller bleu (qui est limité au mode paysage) s'affiche en mode Portrait.

PS Toutes mes methods de rotation (affichées ci-dessus) sont appelées normalement (d'ailleurs pourquoi ces methods sont-elles appelées autant de fois par transition d'écran – 5-6 fois)

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation ne se fait pas appeler en poussant

Toutes les orientations (sauf portraitUpsideDown) sont incluses dans plist.

La question est – comment forcer la rotation à l'orientation soutenue dans chaque controller?

Je vous suggère de postr ici (comme réponses) n'importe quel code fonctionnant à 100% pour gérer les rotations dans ios6 (par exemple si vous en avez pour iPad avec SplitController) – Je garderai cette question dans les favoris pour avoir tout en un seul endroit quand j'ai besoin gérer certaines situations spécifiques. À votre santé!

AJOUTÉ: S'il vous plaît, ne postz pas ceci comme réponse de paysage en portrait . J'espère qu'il y a une façon plus élégante de le faire.

Using -[UIDevice setOrientation:] est une API privée, et votre application sera rejetée. Voir cette question .

Ce que vous requestz n'est pas possible en utilisant l'API publique et n'est pas non plus recommandé du sharepoint vue HIG. Ce qui est supporté et que vous devez implémenter, c'est la présentation modale des différents controllers de vue avec différentes orientations d'interface supscopes. C'est pourquoi l'implémentation par défaut de UINavigationController est de toujours tourner; il suppose que tous les controllers de vue ont les mêmes orientations d'interface sockets en charge.

Prenez par exemple la lecture video sur iPhone. Ouvrez les applications video (fournies avec iOS). Le controller de vue racine prend uniquement en charge l'orientation portrait. Cependant, démarrez une video et un controller de vue modale apparaît, qui ne prend en charge que les orientations de l'interface paysage. Cela semble exactement le comportement que vous souhaitez atteindre.

C'est pourquoi preferredInterfaceOrientationForPresentation n'est pas appelé. preferredInterfaceOrientationForPresentation n'est appelée que lors de l'utilisation de presentViewController:animated:

Si vous avez besoin d'une barre de navigation à chaque étape de votre scène, vous devrez placer chaque controller de vue modale avec un controller de navigation. Vous pouvez ensuite transmettre datatables requirejses dans prepareForSegue: en accédant à topViewController de l'object controller de navigation dans la section.


Voici un exemple de projet qui se comporte correctement selon vos besoins (ou du less vous donnera des idées pour l'implémenter):

http://www.mediafire.com/?zw3qesn8w4v66hy

Ma valeur de deux cents.

Vous pouvez présenter une vue modale transparente vide rapidement, puis la rejeter , peut-être sur ViewDidLoad: ou viewWillAppear: sur votre class ViewController et ViewControllerSecond comme une solution de contournement rapide.

En outre, dans le storyboard, vous pouvez définir visuellement l' orientation de class de ViewController .

utilisez cette ligne pour modifier l'orientation par programme … travail 100%

 [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; 

et aussi quand vous ajoutez cette ligne à ce moment-là un avertissement apparaît et pour supprimer cet avertissement il suffit d'append le code ci-dessous sur votre file d'implémentation .. en haut.

 @interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere) - (void) setOrientation:(UIInterfaceOrientation)orientation; @end 

et après cela dans la méthode ci-dessous, écrivez simplement ce code si nécessaire.

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return your supported orientations if (currentMainView==blueOne) { return toInterfaceOrientation== UIInterfaceOrientationPortrait; } } 

J'ai une situation similaire dans l'une de mes applications (mais notez que je n'utilise pas UINavigationController).

Modifiez les methods shouldAutorotate dans vos deux viewControllers:

 //in blue (landscape only) -(BOOL)shouldAutorotate{ if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { return YES; } else { return NO; } } //in red (portrait only) -(BOOL)shouldAutorotate{ if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { //note that UIInterfaceOrientationIsPortrait(self.interfaceOrientation) will return yes for UIInterfaceOrientationPortraitUpsideDown return YES; } else { return NO; } } 

Gardez les methods supportedInterfaceOrientations identiques.

 #pragma mark- Orientation Delegate Method: - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { Orientation = [UIApplication sharedApplication].statusBarOrientation; if (Orientation == UIInterfaceOrientationLandscapeLeft || Orientation == UIInterfaceOrientationLandscapeRight) { // self.scrollView.contentOffset = CGPointMake(self.view.bounds.size.width,1200); [scrollView setScrollEnabled:YES]; [scrollView setContentSize:CGSizeMake(768, 2150)]; }else if (Orientation == UIInterfaceOrientationPortrait || Orientation == UIInterfaceOrientationPortraitUpsideDown) { [scrollView setScrollEnabled:YES]; [scrollView setContentSize:CGSizeMake(768, 1750)]; } } 

Afin d'utiliser la navigation avec orientation set, vous devriez prendre un groupe de viewcontrollers comme un tableau.

Après cette vérification des methods suivantes,

 -(BOOL)shouldAutorotate { return [[self.viewControllers lastObject] shouldAutorotate]; } -(NSUInteger)supportedInterfaceOrientations { return [[self.viewControllers lastObject] supportedInterfaceOrientations]; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation]; } 

ces changements dans vos methods vous aideront beaucoup.

Profitez de la programmation!