2010-05-14 3 views
7

Mon application dispose d'environ 10 UIViewControllers différents, dont un seul que je veux passer en mode paysage si l'appareil est pivoté. (Tout le reste, je veux garder en portrait.)Comment implémenter la rotation de UIViewController en réponse aux changements d'orientation?

Afin d'implémenter la rotation sur cette vue, j'ai dû implémenter la méthode 'shouldAutorotate' de son contrôleur et retourner YES. Puisque cette vue est accessible via un contrôleur de navigation, j'ai également eu besoin de créer une sous-classe de UINavigationController qui implémente 'shouldAutorotate' et retourne YES.

Cette solution fonctionne, mais trop bien. Je trouve que tous les UIViewControllers que j'appuie sur ma sous-classe de UINavigationController répondent à la rotation, même si j'implante 'shouldAutorotate' et renvoie NO. (Rappelez-vous: je veux seulement qu'un UIViewController particulier réponde à la rotation, pas à tous dans la pile du contrôleur de navigation.)

Alors, ma question est: comment puis-je faire mieux? Toutes les solutions que je peux trouver semblent 1) lourdes, et 2) pire, ne semblent pas fonctionner.

Merci beaucoup.

Répondre

0

J'ai vu des exemples en utilisant la façon dont vous le faites mais je n'ai pas pu le faire fonctionner correctement. J'ai trouvé la meilleure façon de le faire à partir d'exemples de pommes. Fondamentalement, vous implémentez un presentModalViewController et créez une autre vue. UIKit fait une animation de rotation de base et se fane entre la vue. Vous devez implémenter la vue pivotée en tant que classe déléguée afin qu'elle puisse rappeler sa classe appelante pour la rejeter et mettre à jour l'orientation.

- (void)orientationChanged:(NSNotification *)notification 
{ 
    // We must add a delay here, otherwise we'll swap in the new view 
    // too quickly and we'll get an animation glitch 
    NSLog(@"orientationChanged"); 
    [self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0]; 
} 

Et puis pour afficher un écran de paysage:

- (void)updateLandscapeView 
{ 
PortraitView *portraitView = [[PortraitView alloc] init]; 
portraitView.delegate = self; 
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; 
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) 
{ 
    [self presentModalViewController: portraitView animated:YES]; 
    isShowingLandscapeView = YES; 
    } 
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView) 
{ 
    [self dismissModalViewControllerAnimated:YES]; 
    isShowingLandscapeView = NO; 
    } 
[portraitView release]; 
} 
1

Je le fais en ayant un contrôleur de vue racine (cela pourrait être un UITabBarController) et c'est la méthode viewDidLoad i abonner à des événements de rotation:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didRotate:) 
                 name:@"UIDeviceOrientationDidChangeNotification" 
                 object:nil]; 

Puis dans la didRotate: méthode que je regarde ce qui est visible voir contrôleur lorsque la rotation est arrivé, et quelle orientation le téléphone est en:

- (void) didRotate:(NSNotification *)notification { 
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 

/* 
    DEVICE JUST ROTATED TO PORTRAIT MODE 

orientation == UIDeviceOrientationFaceUp || 
orientation == UIDeviceOrientationFaceDown 

*/ 
if(orientation == UIDeviceOrientationPortrait) { 





/* 
    DEVICE JUST ROTATED TO LANDSCAPE MODE 
*/ 
}else if(orientation == UIInterfaceOrientationLandscapeLeft || 
     orientation == UIInterfaceOrientationLandscapeRight) { 






} 

} 

Dans ce didRotate: vous pouvez voir quel est le viewController visible et faire ce que vous voulez à partir de là. Je présente un contrôleur de vue modale en mode paysage lorsqu'un contrôleur de vue particulier est visible et que le téléphone est mis en mode paysage. Si un autre contrôleur de vue est visible, j'ignore l'événement.

Je forcer mon contrôleur de vue modale à afficher en mode paysage dans sa méthode viewWillAppear - je peux donner à n'importe qui ce code s'il le veut.

Espérons que cela aide.

Dave

1

retours OUI sur la sous-classe du contrôleur de navigation uniquement si [[NavController topViewController] isKindOfClass: [classe RotatingViewController]]

2

lorsque vous implémentez UINavigationController, cette classe est votre parent qui contrôle tous les enfants voientContrôleurs qui seront poussés dans la pile.Par conséquent, le RootViewController est le seul contrôleur qui indique Oui ou Non à l'autorotation. Même si, vous passez Oui à la rotation automatique dans les contrôleurs de vue enfants, ils ne comptent pas!

C'est la nature de UINavigationController. Donc, pour le changer, vous avez deux choix:

1- Manipulez-le manuellement, ce qui nécessite de passer par des codes encombrants.

2- Modifiez votre conception afin qu'elle soit plus compatible avec UINavigationController. Cette vue unique qui doit pivoter doit être appelée par le RootViewController (pas par le contrôleur de vue racine de navigation - ils sont nommés de la même manière, mais sont totalement différents), la vue qui héberge NavController. Et quand l'appareil tourne, il va soit pousser le NavController à la vue ou l'autre. 3- L'autre méthode, qui fonctionne également, mais qui n'est pas recommandée parce qu'elle viole le concept de MVC, est que votre NavController peut écouter les notifications. Cette vue enfant particulière qui PEUT et DEVRAIT tourner peut émettre une notification - par ex. rotateMe, et une fois que le NavController l'a entendu, il tourne. Comme je l'ai dit, cela fonctionnera, mais il viole le modèle MVC - ce qui est bien pour Apple, mais du point de vue de la programmation n'est pas recommandé.

Si vous avez besoin d'explications supplémentaires à propos de l'une d'entre elles, s'il vous plaît faites le moi savoir.

Questions connexes