Подтвердить что ты не робот

Скрытие UITavigationController UIToolbar во время просмотраWillDisappear:

У меня есть приложение iPhone с меню UITableView. Когда выбрана строка в таблице, соответствующий контроллер представления помещается в стек приложения UINavigationController.

Моя проблема в том, что для MenuViewController не нужна панель инструментов, но UIViewControllers, которые выталкиваются в стек, делают. Каждый UIViewController, который получает нажатые вызовы setToolbarHidden:animated: в viewDidAppear:. Чтобы скрыть панель инструментов, я вызываю setToolbarHidden:animated: в viewWillDisappear:.

Отображение панели инструментов работает так, что при появлении толкаемого представления панель инструментов соскальзывает, и вид изменяется правильно. Однако, когда нажата кнопка "Назад", панель инструментов сдвигается вниз, но вид не изменяется. Это означает, что в нижней части представления есть черная полоса, по мере перехода к другому представлению. Я попытался добавить высоту панели инструментов к высоте представления до сокрытия панели инструментов, но это заставляет анимировать представление во время переход, чтобы все еще была черная полоса.

Я понимаю, что могу управлять своим UIToolbar, но я бы хотел использовать UINavigationControllers, встроенный в UIToolbar для удобства.

Этот пост форума упоминает ту же проблему, но об этом не упоминается.

4b9b3361

Ответ 1

Я тоже испытал эту проблему. В моем случае единственный способ, которым я нашел, чтобы скрыть панель инструментов, не показывая фон окна, - это вызвать [self.navigationController setToolbarHidden:YES animated:animated] в вашем контроллере вида -viewDidAppear:.

Ответ 2

Я не был доволен ответами на этот вопрос, поэтому я разместил свои собственные: Ссылка на контроллер представления источника и контроллер точки назначения в то же время

В ответ я исправил свою проблему. Это может сработать и для вас (хотя этот вопрос довольно старый, я подумал, что это может помочь кому-то вроде меня, который прочитал это сообщение полдюжины раз, чтобы найти подсказку).

Вот что я сделал. Я не знаю, являются ли протоколы маркеров идиоматическими objective-c или нет, но я сравниваю их с такими атрибутами, как я бы использовал в С#, поэтому у меня есть этот протокол-маркер:

@protocol HidesNavigationItem
@end

Я добавил UINavigationControllerDelegate в свой AppDelegate. Я еще не уверен, хорошо ли это. Я думал о том, чтобы сохранить эту реализацию в другом объекте, но на данный момент я это сделал. Здесь реализация:

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

Таким образом, я могу просто установить протокол маркеров в моей реализации UIViewController так:

@interface MyViewController : UIViewController <HidesNavigationItem>

Если у меня нет этого интерфейса, он возвращает его.

Наконец, в приложении appDelegate: метод didFinishLaunchingWithOptions: я подключаю делегат следующим образом:

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

Теперь у меня нет черных ящиков и нет Чеширского кота. Разумеется, мое решение касалось навигационной панели, но я уверен, что она работает одинаково для панели инструментов. Это очень похоже на ответ Danra, за исключением того, что я получаю черный ящик без анимированного анимированного.

Ответ 3

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

Реализация метода hidesBottomBarWhenPushed для этого UIViewController:

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

Или до нажатия в UIViewController установите значение hidesBottomBarWhenPushed:

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

Ответ 4

Попробуйте внедрить UINavigationControllerDelegate и установить его в свойстве делегирования контроллера навигации. Это обеспечило мне то, что вы описываете в своем посте, без видимых артефактов.

Следующий код предполагает, что secondController вставляется в навигационное представление посредством действия, выполняемого в первом контроллере.

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 - это просто вспомогательный метод:

AppDelegate_Shared.m

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

Ответ 5

Чтобы показать панель инструментов в новом контроллере представления, просто добавьте это:

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

Чтобы скрыть панель инструментов:

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

При перемещении между экранами нажмите новый контроллер просмотра со следующим кодом:

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

и если у него есть другое состояние панели инструментов (скрытое/показанное), тогда будет показана приятная анимация скрытия/отображения панели инструментов.

Ответ 6

Проблема заключается в том, что кадр UITableView установлен таким образом, что он не перекрывается с UIToolbar. То есть он находится чуть выше UIToolbar. Когда вы нажимаете следующий UIViewController на стек UINavigationController, удаляя UIToolbar, ничего не показывать, кроме UIWindow позади него, , если вы не помещаете что-то там на своем месте.

Один способ обхода без неудобной анимации после перехода состоит в том, чтобы поместить ваш UITableView в контейнер UIView ", который разделяет тот же фрейм, что и ваш обычный вид, но подставляет UIToolbar желаемый цвет, который вы хотите во время перехода (например, белый).

Чтобы ввести нижнюю границу, вы можете установить UIViewController на wantsFullScreenLayout = YES. Затем вы убедитесь, что ваш UITableView имеет тот же фрейм, который был бы до использования контейнера. то есть он находится ниже панели навигации и над панелью инструментов.

Это можно сделать более элегантным, написав пользовательский UIViewController и использовать это вместо UITableViewController, или подкрадываясь и вставляя новый UIView "контейнер" под UITableView в существующий UITableViewController.

Ответ 7

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

self.navigationController.toolbar.barStyle = UIBarStyleBlackTranslucent;

in viewDidLoad.

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

Ответ 8

Я согласен с ответом Джеффа. Но есть сбой в пользовательском интерфейсе, если я скрою панель инструментов в методе -viewDidAppear viewController, через который будут сдвинуты разные viewControllers.

Чтобы избежать этого, я экспериментировал и обнаружил, что вызов -setToolbarHidden в вызове -viewWillAppear действительно скрывает панель инструментов, но, как говорится в вопросе, расширение, хотя и расширенное, не будет занято строками tableview.

Чтобы исправить это, я изменил следующий код и теперь он работает без сбоя:

- (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];
.
.
.
}

Ответ 9

Управление состоянием панели инструментов (т.е. какой VC требуется/не нуждается в панели инструментов) быстро становится сложным.

У меня был успех с соблюдением этого правила:

Для каждого контроллера представления в viewWillAppear(), решите, нужна ли ему панель инструментов или нет, затем вызовите navigationController?.setToolbarHidden(true or false, animated: animated) соответственно.

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

Ответ 10

Это просто дикий удар в темноте, но, возможно, вы должны запустить runloop один раз после скрытия панели инструментов:

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

Ответ 11

У меня была такая же проблема, и вот решение, которое сработало для меня. Предположим, вы нажимаете SomeUIViewController на свой навигационный стек.

Определите этот (закрытый) ivar в интерфейсе SomeUIViewController:

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

Внедрите следующие методы 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];
}

Идея состоит в том, что вы хотите скрыть панель инструментов, принадлежащую навигационному контроллеру, после исчезновения SomeUIViewController. Таким образом, вы избегаете любых нежелательных экспонатов.

ОТКАЗ

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