2010-02-26 13 views
28

Tengo una aplicación de iPhone con un menú UITableView. Cuando se selecciona una fila en la tabla, se inserta el controlador de vista apropiado en la pila de la aplicación UINavigationController.Ocultar una UIToolbar de UINavigationController durante viewWillDisappear:

Mi problema es que el MenuViewController no necesita una barra de herramientas, pero el UIViewControllers que se insertan en la pila lo hacen. Cada UIViewController que recibe llamadas presionadas setToolbarHidden:animated: en viewDidAppear:. Para ocultar la barra de herramientas, llamo al setToolbarHidden:animated: en viewWillDisappear:.

Mostrando la barra de herramientas funciona, de modo que cuando aparece la vista presionada la barra de herramientas se desliza hacia arriba y la vista cambia de tamaño correctamente. Sin embargo, cuando se presiona el botón Atrás, la barra de herramientas se desliza hacia abajo, pero la vista no cambia de tamaño. Esto significa que hay una franja negra en la parte inferior de la vista cuando la otra vista realiza la transición. Intenté agregar la altura de la barra de herramientas al alto de la vista antes de ocultar la barra de herramientas, pero esto hace que la vista se vea animada durante el transición para que todavía haya una barra negra.

Me doy cuenta de que puedo administrar mi propia UIToolbar, pero me gustaría usar UINavigationControllers construido en la UIToolbar para mayor comodidad.

This forum post menciona el mismo problema, pero no se menciona ninguna solución.

Respuesta

-1

Esto es sólo una puñalada salvaje en la oscuridad, pero tal vez debería dejar correr el runloop vez después de ocultar la barra de herramientas:

[viewController setToolbarHidden:YES animated:YES]; 
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]]; 
+0

No, eso no hace la diferencia. –

+0

Bummer. Valió la pena intentarlo. – diederikh

23

Yo también he tenido este problema. En mi caso, la única forma que encontré para ocultar exitosamente la barra de herramientas sin mostrar el fondo de la ventana es llamar al [self.navigationController setToolbarHidden:YES animated:animated] en el método -viewDidAppear: de su controlador de vista.

+0

Upvoted. Esta es la única solución que funcionó sin que se filtrara el fondo. La barra de herramientas tiene una desaparición de "gato de Cheshire", es decir, desaparece después de que la nueva vista está en su lugar en lugar de antes, pero es mucho mejor que tener el fondo sangrando. – lambmj

+0

Tan simple. Tan sencillo. (Aunque preferiría esconderlo durante la transición.) – griotspeak

+2

Parece que la parte '... animada: animada' tiene sentido aquí - funciona incluso en el método' -viewWillAppear: '. – adruzh

-3

Tuve el mismo problema y aquí está la solución que funcionó para mí. Digamos que está presionando SomeUIViewController en su pila de navegación.

Definir esta Ivar (privado) en la interfaz de SomeUIViewController:

// keep a reference to the navigation controller for use in viewDidDisappear:(BOOL)animated method 
UINavigationController * _navigationController; 

implementar los siguientes métodos de SomeUIViewController:

- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    // here, your controller still has a reference to self.navigationController 
    _navigationController = [self.navigationController retain]; 
} 

- (void)viewDidDisappear:(BOOL)animated { 
    // at this point, self.navigationController = 0x0, so 
    // use your retained reference to the navigation controller to perform any last minute operations, then release 

    [_navigationController setToolbarHidden:YES]; 
    [_navigationController release]; 

    [super viewDidDisappear:animated]; 
} 

La idea es que se desea ocultar la barra de herramientas de propiedad de la El controlador de navegación después deSomeUIViewController ha desaparecido. De esta forma, evitará cualquier artefacto de visualización no deseado.

RENUNCIA

Esto no es más que una respuesta que muestra una solución solución para el problema indicado. Está destinado únicamente a señalar un detalle del funcionamiento interno del marco. También se entiende como un ejemplo de lo que no para enviar a Apple AppStore.

1

Intente implementar un UINavigationControllerDelegate y configúrelo en la propiedad delegada de su controlador de navegación. Esto logró para mí lo que está describiendo en su publicación, sin artefactos visibles.

El siguiente código supone que secondController se inserta en la vista de navegación mediante una acción realizada en el firstController.

MyNavigationControllerDelegate.h

@interface MyNavigationControllerDelegate : NSObject<UINavigationControllerDelegate> { 
} 

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated; 
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated; 

@end 

MyNavigationControllerDelegate.m

#import "MyNavigationControllerDelegate.h" 
#import "AppDelegate_Shared.h" 

@implementation MyNavigationControllerDelegate 

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    if ([AppDelegate_Shared sharedDelegate].firstController == viewController) { 
     [navigationController setNavigationBarHidden:TRUE]; 
     [navigationController setToolbarHidden:FALSE]; 
    } 
} 

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    if ([AppDelegate_Shared sharedDelegate].secondController == viewController) { 
     [navigationController setNavigationBarHidden:FALSE]; 
     [navigationController setToolbarHidden:TRUE]; 
    } 
} 

@end 

sharedDelegate es sólo un método de ayuda:

AppDelegate_Shared.m

+ (AppDelegate_Shared*)sharedDelegate { 
    return (AppDelegate_Shared*)[[UIApplication sharedApplication] delegate]; 
} 
1

Para mostrar la barra de herramientas en el nuevo controlador de vista sólo tiene que añadir esto:

- (void)viewWillAppear:(BOOL)animated 
{ 
    [self.navigationController setToolbarHidden:NO animated:animated]; 
    [super viewWillAppear:animated]; 
} 

Para ocultar la barra de herramientas:

- (void)viewWillAppear:(BOOL)animated 
{ 
    [self.navigationController setToolbarHidden:YES animated:animated]; 
    [super viewWillAppear:animated]; 
} 

Al viajar entre las pantallas impulso nuevos ver el controlador con el siguiente código:

SettingsRecordingViewController *vc = [[SettingsRecordingViewController alloc] initWithNibName:@"SettingsRecordingViewController" bundle:[NSBundle mainBundle]]; 
[self.navigationController pushViewController:vc animated:YES];  
[vc release]; 

y si tiene un estado diferente de la barra de herramientas (oculta/mostrada), se mostrará una buena animación de ocultar/mostrar la barra de herramientas.

1

El problema aquí es que el marco UITableView está configurado para que no se superponga con el UIToolbar. Es decir, se encuentra justo por encima del UIToolbar. Cuando presiona el siguiente UIViewController en la pila UINavigationController, mientras elimina el UIToolbar, no hay nada que mostrar excepto el UIWindow detrás de él, a menos que ponga algo allí en su lugar.

Una solución sin la animación incómoda después de la transición es colocar su UITableView en un "contenedor" UIView que comparte el mismo marco que la vista normal, pero solapa por debajo del UIToolbar con el color deseado que desea ver durante la transición (por ejemplo, blanco).

Para representar el solapamiento, puede configurar UIViewController en wantsFullScreenLayout = YES. Luego se aseguraría de que su UITableView tenga el mismo marco que antes del uso del contenedor. es decir, se encuentra debajo de la barra de navegación y encima de la barra de herramientas.

Esto se puede hacer más elegante escribiendo una costumbre UIViewController y el uso que en lugar de la UITableViewController, o por ser astuto e insertando el nuevo "contenedor" UIView debajo de la UITableView existente en su UITableViewController.

6

que no estaba satisfecho con las respuestas en esta pregunta por lo que he publicado mi propia: Reference to source view controller and destination view controller at the same time

La respuesta me fijo mi problema.También puede funcionar para la tuya (aunque esta pregunta es bastante antigua, pensé que esto podría ayudar a alguien como yo que leyó esta publicación media docena de veces buscando una pista).

Esto es lo que hice. No sé si los protocolos son marcadores idiomática Objective-C o no, pero yo los comparo a atributos como si hubiera utilizar en C#, así que tengo este protocolo marcador:

@protocol HidesNavigationItem 
@end 

he añadido a mi UINavigationControllerDelegate AppDelegate. Todavía no estoy seguro de si eso es algo bueno o no. Pensé en mantener esa implementación en otro objeto, pero por ahora, aquí es donde lo puse. Aquí está la aplicación:

#pragma mark Navigation Controller Delegate 
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    [navigationController setNavigationBarHidden:[viewController conformsToProtocol:@protocol(HidesNavigationItem)] animated:animated]; 
} 

De esta manera, puedo poner mi protocolo marcador en mi aplicación UIViewController así:

@interface MyViewController : UIViewController <HidesNavigationItem> 

Si no tengo esa interfaz, se pone de nuevo.

Por último, en la solicitud de mi AppDelegate: didFinishLaunchingWithOptions: método, puedo conectar el delegado de la siguiente manera:

if ([self.window.rootViewController isMemberOfClass:[UINavigationController class]]) 
    ((UINavigationController*)self.window.rootViewController).delegate = self; 

Ahora me sale cajas negras y ningún gato de Cheshire. Mi solución fue con respecto a la barra de navegación, por supuesto, pero estoy seguro de que funciona igual para la barra de herramientas. Esto es muy similar a la respuesta de Danra, excepto que obtengo la caja negra sin el "animado: animado".

+1

Todavía me sale una barra negra con esta técnica. –

0

Utilizo una imagen de fondo personalizada para el fondo de la barra de herramientas y una imagen personalizada para el fondo de la tabla. Estaba teniendo el mismo problema con la barra negra en la parte inferior cuando la vista hacía una transición hacia adelante y hacia atrás desde otra vista de tabla. Sin embargo, establecí el

self.navigationController.toolbar.barStyle = UIBarStyleBlackTranslucent; 

en viewDidLoad.

Esto establece la imagen de fondo en el tamaño de potencial completo del fondo, que si tuviera una barra de herramientas transparente tendría sentido. Probablemente no sea una buena solución cuando está utilizando la barra de herramientas opaca estándar, pero para aquellos que personalizan la barra de herramientas de todos modos, puede obtener lo mejor de ambos mundos.

4

Para el UIViewController que no necesita una barra de herramientas cuando se empuja se puede considerar el uso de cualquiera

La implantación del método hidesBottomBarWhenPushed para que UIViewController:

// method to be added to the UIViewController that has no toolbar 
- (BOOL) hidesBottomBarWhenPushed { 
    return YES; 
} 

O antes de empujar en el UIViewController, establezca el valor of HidesBottomBarWhenPushed:

viewControllerWithNoToolBar.hidesBottomBarWhenPushed = YES 
[self.navigationController pushViewController:viewControllerWithNoToolBar animated:YES]; 
0

Estoy de acuerdo con la respuesta de Jeff. Pero hay un error de UI si oculto la barra de herramientas en el método -viewDidAppear del viewController a través del cual se presionan diferentes viewControllers.

Para evitar esto, estaba experimentando y descubrí que llamar a -setToolbarHidden en la llamada -viewWillAppear de hecho oculta la barra de herramientas, pero como dice la pregunta, la vista aunque expandida no estaría ocupada por las filas de la vista de tabla.

Para solucionar este problema, me han cambiado a siguiente código y ahora funciona sin el problema técnico:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
. 
. 
. 
    [self reframeRowHeight]; 
    [self.menuItemTableView addObserver:self 
          forKeyPath:@"frame" 
           options:NSKeyValueObservingOptionNew 
           context:nil]; 
    [self.menuItemTableView setBounces:NO]; 
. 
. 
. 
} 
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"frame"]) 
    { 
     [self reframeRowHeight]; 
    } 
} 

-(void)reframeRowHeight 
{ 

    [self.menuItemTableView setRowHeight:self.menuItemTableView.frame.size.height/self.menuItems.count]; 
    [self.menuItemTableView reloadData]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
. 
. 
. 
    // Bad Apple! - http://stackoverflow.com/questions/2339721/hiding-a-uinavigationcontrollers-uitoolbar-during-viewwilldisappear 
    [self.navigationController setToolbarHidden:YES animated:YES]; 
. 
. 
. 
} 
0

La gestión de la barra de herramientas de estado (es decir, que necesita VC/no necesita la barra de herramientas) se complica rápidamente.

que he tenido éxito con esta regla siguiente:

Para cada controlador de vista, en viewWillAppear(), decidir si se necesita una barra de herramientas o no, a continuación, llamar navigationController?.setToolbarHidden(true or false, animated: animated) respectivamente.

De esta forma, cada controlador de vista comienza con el estado correcto de la barra de herramientas y no tiene que preocuparse por "restaurar" el estado de la barra de herramientas cuando se descarta el controlador de vista.

Cuestiones relacionadas