2009-04-08 15 views
7

Me gustaría implementar lo siguiente. Cuando el usuario gira el iPhone, quiero crear una instancia de un nuevo UIViewController (automáticamente al girar, sin hacer clic en un botón ni realizar una acción similar) y mostrar al usuario una vista manejada por este nuevo UIViewController en orientación horizontal. ¿Cómo hacer esto correctamente?¿Rotar el iPhone e instaurar un nuevo UIViewController?

He intentado crear una instancia del nuevo controlador en los métodos willRotateToInterfaceOrientation y didRotateFromInterfaceOrientation, pero ninguno de estos métodos se llama !. Sospecho que esto se debe a que el controlador actual es empujado por un controlador de navegación que es manejado por un tabBarController. ¿Cualquier pista? Un simple fragmento de código sería muy apreciado.

Gracias de antemano.

Respuesta

7

Implementé este tipo exacto de comportamiento en una aplicación y la clave es asegurarme de que cualquier controlador principal implemente shouldAutorotateToInterfaceOrientation y que su controlador de vista actual también lo implemente. En mi caso, estoy usando un controlador de pestañas que intercepta la llamada a shouldAutorotateToInterfaceOrientation y tuve que anular el control de pestañas para evitar que la llamada se solucionara. El comportamiento predeterminado de los controladores de vista es mostrar solo en modo retrato.

por lo que necesita para obligarlos a permitir que todos los cambios de orientación a través de: - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation { retorno SÍ; }

A continuación, con el fin de cargar un nuevo controlador de vista que debe responder a:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 
    if((fromInterfaceOrientation == UIInterfaceOrientationPortrait) || 
    (fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)) 
    {  
    // Load the view controller you want to display in landscape mode... 
    } 
} 

y también puede utilizar:

-(void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

detectar que el cambio de orientación está por venir.

En mi caso estoy usando didRotateFromInterfaceOrientation para comprobar si la última orientación fue vertical y si es así cargar la vista que quiero que se muestre en modo horizontal.

Implementé los mismos métodos en el viewcontroller que estoy cargando y es responsable de detectar cuándo la orientación cambia de nuevo a portrait y se descarta de la vista.

Espero que ayude un poco.

Paul

+0

¿Debo hacer una subclase del tabBarController inicial para agregar el método shouldAutorotateToInterfaceOrientation? Este controlador tabBar se ha configurado utilizando IB y unas pocas líneas un código en el delegado de la aplicación. He seguido todos los pasos, pero no se ha llamado a didRotateFromInterfaceOrientation. –

+1

Ok, he subclasificado el tabBarController, agregando shouldAutorotateToInterfaceOrientation y ahora todo funciona. Muchas gracias por su ayuda. Saludos cordiales. –

+0

Prefiero no usar UITabBarController en absoluto y en su lugar usar un UIViewController con una UITabBar. – mk12

1

¿Implementa shouldAutorotateToInterfaceOrientation? De lo contrario, puede ser por eso que no recibes los mensajes.

+0

Sí, lo creo. Incluso simplemente devolver SI en shouldAutorotateToInterfaceOrientation no funciona. –

29

una forma más limpia es no utilizar UIInterfaceOrientation para la rotación.

Por qué, porque entonces su interfaz o vista 1 realmente gira. Esto significa que tiene que girarlo hacia atrás para volver a mostrarlo después de que se elimine la vista 2. Para compensar esto, simplemente suscribo a UIDeviceOrientation notificaciones. Sutilmente diferente. La vista 1 NO tiene que admitir autorrotación para que este método funcione.En viewDidLoad introduzca el siguiente código:

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

A continuación, sólo se define el método detectOrientation:

-(void) detectOrientation { 

    if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || 
      ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) { 

     //load view 2 


    } else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait) { 

     // load view 1 

    } 
} 

Ahora ninguno de sus puntos de vista deben apoyar autoratation! No obstante, tendrá que llevar a cabo una transformación en la visión 2 antes de la carga:

-(void) transformView2ToLandscape { 

    NSInteger rotationDirection; 
    UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation]; 

    if(currentOrientation == UIDeviceOrientationLandscapeLeft){ 
    rotationDirection = 1; 
    }else { 
    rotationDirection = -1; 
    } 

    CGRect myFrame = CGRectMake(0, 0, 480, 300); 
    CGAffineTransform transform = [[self view2] transform]; 
    transform = CGAffineTransformRotate(transform, degreesToRadians(rotationDirection * 90)); 
    [[self view2] setFrame: myFrame]; 
    CGPoint center = CGPointMake(myFrame.size.height/2.0, myFrame.size.width/2.0); 
    [[self view2] setTransform: transform]; 
    [[self view2] setCenter: center]; 

} 

Ése es cómo intercambiar puntos de vista o la rotación sin apoyar la auto rotación en mis puntos de vista.

+1

Esto se ve realmente interesante. Lo intentaré para comprender el rendimiento real, es decir, cuánto más rápido se entrega una notificación y cuánto se tarda en aplicar la transformación. Muchas gracias. –

+0

esto funciona muy bien. especialmente si está usando dos controladores de vista diferentes para dos orientaciones. –

+0

La respuesta "comprobada" responde a la pregunta, pero esta respuesta responde a la pregunta que (idealmente) debería haberse formulado. – DBD

3

De hecho, solo se notifica al controlador de nivel superior. Usted es responsable de notificar a los controladores anidados.

Agregar a su controlador de la barra de pestañas:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
    [self.selectedViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 
} 
+0

Gracias, agregaré esto a mi código. –

+0

No debe estar subclasando UITabBarController. – mk12

+0

@ Mk12: ¿Por qué? ¿Puede una anulación tan pequeña causar problemas? – Kornel

Cuestiones relacionadas