2011-07-29 12 views
6

Esta pregunta se ha hecho mucho, p. here pero por lo que puedo ver aún no se ha respondido en su totalidad.UIModalTransitionStylePartialCurl con UITabBarController

Tengo un UITabBarController con un UINavigationController como el VC raíz de una de las fichas, que a su vez tiene un MKMapView como su vc raíz. El comportamiento que deseo es que el mapa se curve hacia arriba parcialmente, mientras deja la barra de pestañas en su lugar (similar a la aplicación Mapas).

Hasta ahora, todo lo que he conseguido es trabajar para que todo se curve, lo que no es tan agradable.

Las soluciones que he visto son para establecer la propiedad hidesBottomBarWhenPushed en NO, lo que tendría sentido, pero esto no parece funcionar, (a menos que esté haciendo algo mal).

Para mayor claridad, mi código es el siguiente:

MyVC *aView = [MyVC init]; 
aView.modalTransitionStyle = UIModalTransitionStylePartialCurl; 
aView.hidesBottomBarWhenPushed = NO; 

Para la parte que se presenta, me han tratado las dos alternativas siguientes, ninguno de los cuales parecen funcionar:

[self presentModalViewController:updateStatus animated:YES]; 
[[self navigationController] presentModalViewController:updateStatus animated:YES]; 

Cualquier ayuda mucho apreciado.

+0

FYI el método init anterior es sólo un método de conveniencia estática que hace la asignación etc. – danhopwood

Respuesta

4

He buscado en StackOverflow (y en Internet) una solución a este problema. La pregunta se ha formulado muchas veces, pero como usted nota, nunca respondió lo suficiente. Muchos solutions dan una solución aceptable si no es importante si, por ejemplo, una barra de herramientas inferior también se curva.

Others han proporcionado una solución utilizando UIView animaciones/CoreAnimation en lugar de UIModalTransitionStylePartialCurl como un estilo de transición modal; en el peor de los casos, esta es una solución que no está permitida y, en el mejor de los casos, no tiene el mismo efecto que uno obtiene de UIModalTransitionStylePartialCurl (por ejemplo, la forma del rizo es diferente).

Ninguna de estas soluciones ha proporcionado una respuesta que imita la solución de Apple en la aplicación Mapas (es decir, usando UIModalTransitionStylePartialCurl pero dejando UIToolbar sin rizar en la parte inferior de la pantalla).

Continuaré con esta tradición de respuestas incompletas, ya que me pregunta por un UITabBarController y mi solución no aborda específicamente ese caso. Sin embargo, resuelve el problema que tenía, que consistía en obtener un rizo de media página con una barra de herramientas sin rizar en la parte inferior.

Debe haber una manera más elegante de hacer esto, pero así es como lo logré.

El rootViewController de mi AppDelegate es una subclase de UIViewController, que llamaré a TAContainerViewController. TAContainerViewController administra a) el contenido real de la pantalla (el "material que se va a encrespar"), TAContentViewController, yb) el contenido "detrás" de TAContentViewController (por ejemplo, configuración), que llamaré al TAUnderCurlViewController.

Mi instancia de TAContainerViewController tenía propiedades para TAContentViewController y TAUnderCurlViewController. El UIView que era mi contenido era una subvista de la propiedad TAContentViewControllerview; del mismo modo, lo que el usuario ve debajo del rizo es la propiedad view del TAUnderCurlViewController.

En el método de TAContainerViewControllerinit que asegúrese de hacer lo siguiente:

_underCurlVC.modalTransitionStyle = UIModalTransitionStylePartialCurl; 

Y para rizar el contenido para revelar debajo de la página, he creado una acción que llama a este código:

[self.contentVC presentModalViewController:self.underCurlVC animated:YES];` 

donde self es el TAContainerViewController, contentVC es una instancia de TAContentViewController, y underCurlVC es una instancia de TAUnderCurlViewController.

Para descartar la vista, simplemente [self.contentVC dismissModalViewControllerAnimated:YES];.

Parece que se produce algo extraño con el marco de contentVC cuando se descarta la vista modal, por lo que reinicio manualmente el marco cuando se descarta la vista modal.

He publicado un proyecto de muestra con más detalles en Github. Esperemos que alguien pueda tomar esto y convertirlo en una solución ligeramente más elegante, o expandirlo para que funcione con UINavigationController o UITabBarController. Creo que el truco es sacar los Controladores de Vista de las relaciones bien definidas en las subclases de Cocoa, así que tal vez subclases de esos Controladores de Vista especiales lo hagan.

1

La respuesta de Tim Arnold fue genial, ¡gracias!

Una trampa a tener en cuenta: la transición modal de página-curvado ocupará toda la pantalla si su controlador de vista de contenido es agregado como elemento secundario del controlador de vista de contenedor. No podría agregarlo como elemento secundario, pero ninguno de los métodos del ciclo de vida de la vista se ejecutará en su controlador de contenido (por ejemplo, viewDidLoad, viewWillAppear), lo que podría ser un problema.

Afortunadamente, hay una forma de evitar esto. En su controlador de contenedores:

  • Agregar el controlador de contenido como un niño en viewDidLoad
  • Retire como un niño en viewDidAppear
  • Re-añadirlo como un niño en viewWillDisappear.

De esta manera, el controlador de contenido obtiene sus métodos de ciclo de vida llamadas, sin dejar de ser capaz de hacer una transición de página-modal rizo sin ocupar toda la pantalla.

Aquí está el código completo de una solución escueto:

@interface XXContainerController : UIViewController 
@property (strong, nonatomic) UIViewController *contentController; 
@property (nonatomic) BOOL curled; 
@end 

@implementation XXContainerController 

@synthesize contentController = _contentController; 
@synthesize curled = _curled; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.contentController = [self.storyboard 
     instantiateViewControllerWithIdentifier:@"SomeControllerInStoryboard"]; 

    // Add content controller as child view controller. 
    // This way, it will receive all the view lifecycle events 
    [self addChildViewController:self.contentController]; 
    self.contentController.view.frame = self.view.bounds; 
    [self.view addSubview:self.contentController.view]; 
    [self.contentController didMoveToParentViewController:self];  
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 

    // Remove the content controller as child view controller. 
    // This way, the modal page curl transition will 
    // not take over the whole screen. 
    // NOTE: need to wait until content controller has appeared 
    // (which will happen later). 
    // Achieve this by running the code at the end of the animation loop 
    [UIView animateWithDuration:0 animations:nil completion:^(BOOL finished) { 
     [self.contentController removeFromParentViewController]; 
    }]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 

    // Add the content controller as child view controller again 
    // so it receives the view lifecycle events 
    [self addChildViewController:self.contentController]; 
} 

- (void)setCurled:(BOOL)curled 
{ 
    if (curled == _curled) return; 

    _curled = curled; 

    // Curl up the content view and show underneath controller's view 
    if (curled) { 
     // Note you can specify any modal transition in storyboard 
     // E.g. page curl, flip horizontal 
     [self.contentController 
      performSegueWithIdentifier:@"SomeModalSegueDefinedInStoryboard" 
      sender:self]; 

    // Uncurl and show the content controller's view again 
    } else { 
     [self.contentController dismissModalViewControllerAnimated:YES]; 

     // Have to do this, otherwise the content controller's view 
     // gets messed up for some reason 
     self.contentController.view.frame = self.view.bounds; 
    } 
} 

@end 
+0

Gracias para la elaboración! Un aspecto incompleto de mi solución es que no utiliza las API adecuadas de contención del controlador de visualización. –

Cuestiones relacionadas