2010-05-14 10 views
7

Mi aplicación tiene aproximadamente 10 diferentes UIViewControllers, de los cuales solo uno de los cuales quiero cambiar al modo horizontal si el dispositivo se gira. (Todo lo demás, quiero mantenerlo en retrato.)¿Cómo implementar la rotación de UIViewController en respuesta a los cambios de orientación?

Para implementar la rotación en esa vista, necesitaba implementar el método 'shouldAutorotate' de su controlador y devolver SÍ. Como se accede a esta vista a través de un controlador de navegación, también tuve que crear una subclase de UINavigationController que implementa 'shouldAutorotate' y devuelve SÍ.

Esta solución funciona, pero demasiado bien. Encuentro que todos los UIViewControllers que presiono en mi subclase de UINavigationController responden a la rotación, incluso si implemento 'shouldAutorotate' y devuelvo NO. (Recuerde: solo quiero un UIViewController particular para responder a la rotación, no todos en la pila del controlador de navegación.)

Entonces, mi pregunta es: ¿cómo puedo hacer esto mejor? Todas las soluciones que puedo encontrar parecen 1) engorrosas, y 2) peores, no parecen funcionar.

Muchas gracias.

Respuesta

0

He visto ejemplos usando la forma en que lo está haciendo pero no pude hacerlo funcionar correctamente. Encontré la mejor manera de hacerlo desde ejemplos de manzanas. Básicamente, implementa un presentModalViewController y crea otra vista. UIKit realiza una animación de rotación básica y se desvanece entre la vista. Debe implementar la vista rotada como una clase de delegado para que pueda volver a llamar a su clase de llamada para descartarla y actualizar la orientación.

- (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]; 
} 

Y a continuación, para mostrar una pantalla de paisaje:

- (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

hago esto por tener un controlador de vista raíz (esto podría ser una UITabBarController) y en el que es el método viewDidLoad i suscribirse a eventos de rotación:

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

Luego, en el didRotate: método miro qué vista controlador es visible cuando la rotación que pasó, y qué orientación del teléfono 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) { 






} 

} 

Dentro de ese didRotate: se puede ver en que es lo visible viewController y hacer lo que quiera a partir de ahí.

Presento un controlador de vista modal en modo horizontal cuando un controlador de vista en particular está visible y el teléfono gira en horizontal. Si hay otro controlador de vista visible, ignoro el evento.

Obligo a mi controlador de vista modal para que se muestre en modo horizontal en su método viewWillAppear - puedo darle a cualquiera este código si lo desean.

Espero que esto ayude.

de Dave

1

se vuelve positivo en el controlador subclase de navegación sólo si [[NavController topViewController] isKindOfClass: [clase RotatingViewController]]

2

al implementar UINavigationController, esta clase es su padre que controla todos los niños verControladores que se insertarán en la pila.Por lo tanto, RootViewController es el único controlador que dice Sí o No a la autorrotación. Incluso si está pasando Sí a la auto rotación en controles de vista de niños, ¡no cuentan!

Esta es la naturaleza de UINavigationController. Entonces, para cambiarlo, tiene dos opciones:

1- Manipule manualmente, lo que requiere que revise algunos códigos engorrosos.

2- Cambie su diseño para que sea más compatible con UINavigationController. Esa única vista que debe rotar, debe ser llamada por RootViewController (no por el Controlador de Vista de Rooteo de Navegación, reciben el mismo nombre, pero son totalmente diferentes), la vista que aloja NavController. Y cuando el dispositivo gira, empujará NavController a la vista o al otro.

3- El otro método, que también funcionará, pero no se recomienda porque viola el concepto de MVC, es que su NavController puede escuchar las notificaciones. Esa vista infantil particular que PUEDE y DEBERÍA rotar puede emitir una notificación, p. rotateMe, y una vez que el NavController lo oye, gira.

Como dije, funcionará, pero viola el modelo MVC, lo cual está bien para Apple, pero desde la perspectiva de la programación no se recomienda.

Si necesita más explicaciones sobre alguna de ellas, hágamelo saber.

Cuestiones relacionadas