it-roy-ru.com

hidesBottomBarWhenPush = НЕТ не работает?

В моем приложении есть UITabBar, который я прячу в первой UIViewController на первой вкладке, поместив эту строку в A ppDelegate :

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

В firstViewController пользователь может нажать UIButton, который помещает новую UIViewController в ту же вкладку. Я хотел бы, чтобы UITabBar снова был виден, когда это произойдет. Я пытаюсь заставить его вернуться так:

//... in firstViewController.m

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

К сожалению, не возвращает UITabBar. Это остается скрытым.

Как правильно вывести бар UITabBar после его скрытия? 

Заранее спасибо.

24
rottendevice

Вот что говорит документация для hidesBottomBarWhenPushed (выделение добавлено):

Если ДА, нижняя строка остается скрытой до тех пор, пока контроллер представления не выскочит из стека.

Таким образом, похоже, что поведение, которое вы видите, именно то, что говорится в документации. Вы начинаете, помещая контроллер представления в стек, который имеет hidesBottomBarWhenPushed = YES. В этот момент помещение других контроллеров представления в стек не изменит скрытность нижней панели. Пока этот первый контроллер представления находится в стеке, нижняя панель останется скрытой.

Поэтому я думаю, что вам придется придумать другой способ достижения цели вашего пользовательского интерфейса. Одним из вариантов будет представление первого контроллера представления в качестве модального контроллера представления поверх представления контроллера панели вкладок. Затем, когда вы хотите перейти ко второму контроллеру просмотра, просто отклоните первый и вуаля. Единственным визуальным отличием будет анимация перехода.

Конечно, есть и другие варианты, но это было первым, что пришло мне в голову.

Удачи!

28
CharlieMezak

Это проблема, которая беспокоила меня некоторое время, и я только нашел решение, которое работает. Свойство hidesBottomBarWhenPushed - очень странный зверь и работает, на мой взгляд, нелогичным образом.

Проблема в том, что когда вы нажимаете новый контроллер представления (или возвращаетесь назад), navigationController спрашивает все просмотр контроллеров (сверху вниз), хотят ли они скрыть нижнюю панель, и если любая из них говорят, что YES панель вкладок будет скрыта, поэтому панель вкладок остается скрытой, несмотря на то, что NO скрывается на новом контроллере представления.

Вот мое решение - переопределить метод получения hidesBottomBarWhenPushed в контроллере представления, для которого вы не хотите иметь панель вкладок, и проверьте, находится ли он на вершине стека:

Objective-C

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

Свифт (не так очевидно, отсюда и фрагмент)

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

Это красиво инкапсулирует логику скрытия/показа в одном месте, так что вам не нужно думать об этом вне контроллера представления, который скрывает.

63
Loz

У меня была такая же проблема, но через 3 часа я нашел решение! В этой теме ответил 8 октября 2010 г. , Дейв Баттон сказал:

Правильный способ использования свойства hidesBottomBarWhenPressed:

self.anotherViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:self.anotherViewController animated:animated];
7
CFIFok

Не уверен, что решение было найдено для этого, но мне только удалось заставить это работать.

Мой сценарий:

У меня есть UITabBarController с 4 элементами панели вкладок . На одном из элементов панели вкладок он загружает UIViewController с кнопками на нем. Кнопки вызывают функцию IBOutlet, которая загружает другую UIViewController, которая содержит панель вкладок внизу.

После многих проб и ошибок ........

В функции IBOutlet я делаю следующее:

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

Это работало нормально с панелью вкладок UITabBarController's, смещенной влево, и моей панелью вкладок с выдвинутого контроллера, скользящей справа.

Очевидно, что с точки зрения функциональности мне нужно сдвинуть начальную панель UITabBarController's обратно при возвращении.

После многих проб и ошибок ........

У меня есть метод viewWillDisappear в UIViewController, который выдвигает UIViewController с панелью вкладок как:

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

Я провел несколько быстрых тестов на этом в симуляторе, и он, кажется, работает нормально.

Некоторые авторы предполагают, что это плохой пользовательский интерфейс, но сейчас я пробую это, чтобы увидеть, как это работает.

Рад получить (коп) любые отзывы. :)

2
Bigboytony

Использование

secondViewController.hidesBottomBarWhenPushed = NO;

Когда вставить некоторые операции

firstViewController.hidesBottomBarWhenPushed = YES;
1
user1316813

Я думаю, что вы неправильно поняли использование шкуры нижнего бара при толкании. Если ДА, нижняя панель остается скрытой до тех пор, пока контроллер представления не выскочит из стека.

Так что, если я правильно понимаю ваш вопрос:

Второй ViewController должен быть ДА, первый ViewController должен быть НЕТ.

1
NWCoder

Я нашел очень простой способ решить эту проблему, создав подкласс UINavigationController. Вы можете сделать то же самое, используя категорию со связанным объектом, но у меня уже был подкласс, поэтому я просто добавил туда код.

Сначала вы добавляете ivar в свой UINavigationController:

@interface CustomNavigationController ()
{
    NSMutableSet *_viewControllersWithHiddenBottomBar;
}

@end

Затем я переопределил методы Push и pop для управления обработкой скрытой логики:

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

Я использую свойство hidesButtomBarWhenPushed для заполнения набора, а затем сбрасываю значение на уровне viewcontroller (поскольку, если какой-либо контроллер представления имеет это свойство, все поверх него также будет скрыто). Чтобы упростить задачу, я использую корневой viewcontroller для управления отображением и скрытием панели вкладок на основе значений в наборе.

Вам также нужно где-то инициализировать набор, я просто использовал initWithRootViewController:.

Это работает довольно легко для меня и является наименее хакерским способом, которым я мог придумать, не принимая на себя никаких существующих анимаций и не обрабатывая случаи Edge.

1
Dima

Этот работает для меня. Благодаря подсказке в каком-то другом потоке, я нашел решение, чтобы скрыть панель вкладок только для одного представления, и восстановить его для любого контроллера представления, который вызывается изнутри. 

Делая так, я могу поддерживать регулярную цепочку навигационных контроллеров. 

Вот что я наконец получил: 

#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;
}

Встроенные комментарии должны объяснить причины каждого утверждения. Хотя могут быть более разумные способы его кодирования. 

Есть еще один побочный эффект в сочетании с сокрытием строки состояния и панели навигации, которые я не хочу скрывать от вас, ребята. 1. При возврате из этого контроллера навигации к вызывающему контроллеру навигации строка состояния и панель навигации на вызывающем контроллере перекрываются, пока устройство не будет повернуто один раз или пока соответствующая вкладка не будет выбрана снова после того, как другая вкладка появится вперед. 2. Когда вызывающий контроллер представления является табличным представлением, и когда устройство находится в горизонтальном режиме при возврате к таблице, тогда таблица отображается в соответствующей ориентации для альбомной ориентации, но она размещается, как если бы она была портретной. Верхний левый угол в порядке, но некоторые ячейки таблицы плюс панель вкладок скрыты под экраном. На правой стороне есть свободное место. Это тоже можно исправить, повернув устройство снова. 

Я буду держать вас в курсе, как только найду решения для этих мелких, но неприятных ошибок. 

0
Hermann Klecker

Установить вид контроллера в  

У меня нет необходимости устанавливать экран в панели вкладок, этот экран настроек в последних двух методах и экран настроек, чтобы нажать любой экран в нижней панели вкладок дисплея. 

override func viewWillAppear(_ animated: Bool) {

     self.hidesBottomBarWhenPushed = true
}

override func viewDidAppear(_ animated: Bool) {

    self.hidesBottomBarWhenPushed = false
}

Спасибо, если у вас есть запрос, который можно задать.

0
Digvijay Gida