hidesBottomBarWhenPushed = NO no funciona?


Tengo un UITabBar en mi aplicación, que estoy ocultando en la primera {[3] } en la primera pestaña poniendo esta línea en la AppDelegate :

// ... in MyAppDelegate.m
firstViewController.hidesBottomBarWhenPushed = YES;

En el firstViewController, el usuario puede empujar un UIButton que empuja un nuevo UIViewController en la misma pestaña. Me gustaría que el UITabBar para ser visible de nuevo cuando esto sucede. Estoy tratando de hacer que vuelva así:

//... in firstViewController.m

secondViewController = [[SecondViewController alloc] init];
secondViewController.hidesBottomBarWhenPushed = NO;
[[self navigationController] pushViewController:secondViewController animated:YES];

Desafortunadamente, no devuelve el UITabBar. Permanece oculto.

¿Cómo puedo llevar correctamente bar el UITabBar después ¿esconderlo?

Gracias de antemano.

Author: Sujay, 2011-04-13

8 answers

Esto es lo que dice la documentación para hidesBottomBarWhenPushed (énfasis añadido):

Si es ASÍ, la barra inferior permanece oculta hasta que el controlador de vista se extrae de la pila.

Así que parece que el comportamiento que estás viendo es justo lo que la documentación dice que sucederá. Comienza empujando un controlador de vista sobre la pila que tiene hidesBottomBarWhenPushed = YES. En ese punto, empujar otros controladores de vista en la pila no cambiará la ocultación de la barra inferior. Mientras que el primer controlador de vista está en la pila, la barra inferior permanecerá oculta.

Así que creo que tendrás que idear una forma diferente de lograr tu objetivo de interfaz de usuario. Una opción sería presentar el primer controlador de vista como un controlador de vista modal sobre la vista del controlador de la barra de pestañas. Luego, cuando quiera ir al segundo controlador de vista, simplemente deseche el primero y listo. La única diferencia visual será la animación de transición.

Seguramente Hay otras opciones también, pero eso me vino primero a la mente.

¡Buena suerte!

 28
Author: CharlieMezak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-01 15:15:39

Este es un problema que me ha molestado durante un tiempo, y solo acabo de encontrar una solución que funciona. La propiedad hidesBottomBarWhenPushed es una bestia muy extraña, y funciona, en mi opinión, de una manera contra-intuitiva.

El problema con esto es que cuando se empuja un nuevo controlador de vista (o pop back) el NavigationController preguntará todos los controladores de vista (de arriba a abajo) si quieren ocultar la barra inferior, y si cualquier de ellos dice YES la barra de pestañas se ocultará, por lo que tabbar permanece oculto a pesar de configurar NO para ocultar en el nuevo controlador de vista.

Aquí está mi solución-anular el hidesBottomBarWhenPushed getter en el controlador de vista que desea no tener una barra de pestañas, y comprobar si está en la parte superior de la pila:

Objetivo-C

- (BOOL) hidesBottomBarWhenPushed
{
    return (self.navigationController.topViewController == self);
}

Swift (no tan obvio, por lo tanto fragmento)

override var hidesBottomBarWhenPushed: Bool {
    get {
        return navigationController?.topViewController == self
    }
    set {
        super.hidesBottomBarWhenPushed = newValue
    }
}

Esto encapsula muy bien la lógica hide/show en un solo lugar, por lo que no tiene que pensar en ello fuera del viewcontroller que hace la ocultación.

 58
Author: Loz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-12 23:05:10

Tuve el mismo problema, pero después de 3 horas me encontraron solución! En este tema respondió Oct 8 '10, Dave Batton dijo:

La forma correcta de usar hidesBottomBarWhenPushed la propiedad es:

self.anotherViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:self.anotherViewController animated:animated];
 7
Author: CFIFok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:45

No estoy seguro de si se encontró una solución para esto, pero acabo de conseguir que esto funcione.

Mi escenario:

Tengo un UITabBarController con 4 elementos de la barra de pestañas. En uno de los elementos de la barra de pestañas carga un UIViewController con botones. Los botones llaman a una función IBOutlet que carga otra UIViewController que contiene la barra de pestañas a en la parte inferior.

Después de muchos ensayos y errores........

En la función IBOutlet, hago lo siguiente:

{
 self.hidesBottomBarWhenPushed = YES;
 /* Push the new controller with tab bar */
}

Esto funcionaba bien con la pestaña UITabBarController's barra deslizante hacia la izquierda y mi barra de pestañas desde el controlador empujado deslizante desde la derecha.

Obviamente desde la perspectiva de la funcionalidad, necesito empujar la barra de alquitrán inicial UITabBarController's de nuevo cuando "retroceda".

Después de muchos ensayos y errores........

Tengo el método viewWillDisappear en el {[3] } que empuja el UIViewController con la barra de pestañas como:

- (void) viewWillDisappear:(BOOL)animated
{
    self.hidesBottomBarWhenPushed = NO;
}

Realicé algunas pruebas rápidas sobre esto en el simulador y parece que funciona bien.

Algunos colaboradores sugieren que esto es mala interfaz de usuario, pero estoy probando esto en este momento para ver cómo funciona.

Feliz de recibir (cop) cualquier retroalimentación. :)

 2
Author: Bigboytony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 18:08:38

Creo que malinterpretaste los Hidesbottombar cuando los usaste. Si es ASÍ, la barra inferior permanece oculta hasta que el controlador de vista se abre de la pila.

Así que si entiendo su pregunta correctamente:

El SecondViewController debe ser el YES, el FirstViewController debe ser el NO.

 1
Author: NWCoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-12 20:57:09

Use

secondViewController.hidesBottomBarWhenPushed = NO;

Cuando insertar algunas operaciones

firstViewController.hidesBottomBarWhenPushed = YES;
 1
Author: user1316813,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-06 12:33:23

Descubrí una manera muy fácil de resolver esto mediante la subclase UINavigationController. Podrías lograr lo mismo usando una categoría con un objeto asociado pero ya tenía una subclase así que simplemente tiré el código allí.

Primero, agregas un ivar a tu UINavigationController:

@interface CustomNavigationController ()
{
    NSMutableSet *_viewControllersWithHiddenBottomBar;
}

@end

Entonces anulé los métodos push y pop para hacerme cargo de manejar la lógica de ocultación:

- (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if(viewController.hidesBottomBarWhenPushed)
    {
        viewController.hidesBottomBarWhenPushed = NO;
        [_viewControllersWithHiddenBottomBar addObject:viewController];
        [self rootViewController].hidesBottomBarWhenPushed = YES;
    }
    else
    {
        [self rootViewController].hidesBottomBarWhenPushed = NO;
    }
    [super pushViewController:viewController animated:animated];
}

- (UIViewController *) popViewControllerAnimated:(BOOL)animated
{
    if([_viewControllersWithHiddenBottomBar containsObject:self.viewControllers[self.viewControllers.count - 2]])
    {
        [self rootViewController].hidesBottomBarWhenPushed = YES;
    }
    else
    {
        [self rootViewController].hidesBottomBarWhenPushed = NO;
    }
    UIViewController *poppedViewController = [super popViewControllerAnimated:animated];
    [_viewControllersWithHiddenBottomBar removeObject:poppedViewController];
    return poppedViewController;
}

- (UIViewController *) rootViewController
{
    return ((UIViewController *)self.viewControllers.firstObject);
}

Utilizo la propiedad hidesButtomBarWhenPushed para rellenar el conjunto y luego restablecer el valor en el viewcontroller nivel (ya que si cualquier controlador de vista tiene esta propiedad establecida, todo lo que esté encima también la tendrá oculta). Para simplificar las cosas utilizo el root viewcontroller para controlar mostrar y ocultar la barra de pestañas basándose en los valores del conjunto.

También necesita inicializar el conjunto en algún lugar, acabo de usar initWithRootViewController:.

Esto funciona bastante a la perfección para mí y es la forma menos hacky que se me ocurrió para hacer esto, sin tomar ninguna animación existente y tener que manejar casos extremos.

 1
Author: Dima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-03 22:24:02

Este funciona para mí. Gracias a una sugerencia en algún otro hilo aquí he encontrado una solución para ocultar la barra de pestañas para una vista cotroller solo y para restablecer para cualquier controlador de vista que se llama desde dentro.

Al hacerlo, puedo mantener la cadena regular de controladores de navegación.

Esto es lo que finalmente obtuve:

#define kTabBarHeight               49 // This may be different on retina screens. Frankly, I have not yet tried.

- (void) hideTabBar:(BOOL)hide {

    // fetch the app delegate
    AppDelegate         *delegate   = [[UIApplication sharedApplication] delegate];

    // get the device coordinates
    CGRect              bounds      = [UIScreen mainScreen].bounds;
    float               width;
    float               height;

    // Apparently the tab bar controller's view works with device coordinates  
    // and not with normal view/sub view coordinates
    // Therefore the following statement works for all orientations. 
    width                   = bounds.size.width;
    height                  = bounds.size.height;

    if (hide) {

        // The tab bar should be hidden too. 
        // Otherwise it may flickr up a moment upon rotation or 
        // upon return from detail view controllers. 
        [self.tabBarController.tabBar setHidden:YES];

        // Hiding alone is not sufficient. Hiding alone would leave us with an unusable black
        // bar on the bottom of the size of the tab bar. 
        // We need to enlarge the tab bar controller's view by the height of the tab bar. 
        // Doing so the tab bar, although hidden, appears just beneath the screen. 
        // As the tab bar controller's view works in device coordinations, we need to enlarge 
        // it by the tab bar height in the appropriate direction (height in portrait and width in landscape)
        // and in reverse/upside down orientation we need to shift the area's origin beyond zero. 
        switch (delegate.tabBarController.interfaceOrientation) {
            case UIInterfaceOrientationPortrait:
                // Easy going. Just add the space on the bottom.
                [self.tabBarController.view setFrame:CGRectMake(0,0,width,height+kTabBarHeight)];
                break;

            case UIInterfaceOrientationPortraitUpsideDown:
                // The bottom is now up! Add the appropriate space and shift the rect's origin to y = -49
                [self.tabBarController.view setFrame:CGRectMake(0,-kTabBarHeight,width,height+kTabBarHeight)];
                break;

            case UIInterfaceOrientationLandscapeLeft:
                // Same as Portrait but add the space to the with but the height
                [self.tabBarController.view setFrame:CGRectMake(0,0,width+kTabBarHeight,height)];
                break;

            case UIInterfaceOrientationLandscapeRight:
                // Similar to Upside Down: Add the space and shift the rect. Just use x and with this time
                [self.tabBarController.view setFrame:CGRectMake(0-kTabBarHeight,0,width+kTabBarHeight,height)];
                break;

            default:
                break;
        }
    } else {
        // reset everything to its original state. 
        [self.tabBarController.view setFrame:CGRectMake(0,0,width,height)];
        [self.tabBarController.tabBar setHidden:NO];
    }

    return; 
}


- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{

    // It is important to call this method at all and to call it here and not in willRotateToInterfaceOrientation
    // Otherwise the tab bar will re-appear. 
    [self hideTabBar:YES];

    // You may want to re-arrange any other views according to the new orientation
    // You could, of course, utilize willRotateToInterfaceOrientation instead for your subViews. 
}

- (void)viewWillAppear: (BOOL)animated { 

    // In my app I want to hide the status bar and navigation bar too. 
    // You may not want to do that. If so then skip the next two lines. 
    self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];

    [self hideTabBar: YES];

    // You may want to re-arrange your subviews here. 
    // Orientation may have changed while detail view controllers were visible. 
    // This method is called upon return from pushed and pulled view controllers.   

    return;
}

- (void)viewWillDisappear: (BOOL)animated {     

    // This method is called while this view controller is pulled
    // or when a sub view controller is pushed and becomes visible
    // Therefore the original settings for the tab bar, navigation bar and status bar need to be re-instated

    [self hideTabBar:NO];

    // If you did not change the appearance of the navigation and status bar in viewWillAppear,
    // then you can skip the next two statements too. 
    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];

    return;
}

Los comentarios en línea deben explicar el razonamiento para cada declaración. Sin embargo, puede haber formas más inteligentes de codificarlo.

Hay uno efecto secundario junto con ocultar la barra de estado y la barra de navegación también, que no quiero ocultar de ustedes. 1. Al regresar de este controlador de navegación al controlador de navegación que llama, la barra de estado y la barra de navegación en el controlador de llamada se superponen hasta que el dispositivo se gire una vez o hasta que la pestaña relacionada se haya elegido nuevamente después de que otra pestaña haya llegado al frente. 2. Cuando el controlador de vista que llama es una vista de tabla y cuando el dispositivo está en modo horizontal cuando volviendo a la tabla, la tabla se muestra en la orientación apropiada para horizontal, pero se presenta como si fuera vertical. La esquina superior izquierda está bien, pero algunas celdas de la tabla y la barra de pestañas están ocultas debajo de la pantalla. En el lado derecho hay un poco de espacio libre. Esto, también, se corrige girando el dispositivo de nuevo.

Lo mantendré actualizado una vez que encuentre soluciones para estos errores menores pero desagradables.

 0
Author: Hermann Klecker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-07 18:52:52