Скрытие UIToolbar UINavigationController во время просмотра исчезнет: - PullRequest
29 голосов
/ 26 февраля 2010

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

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

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

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

В этом сообщении на форуме упоминается та же проблема, но обходного пути не упоминается.

Ответы [ 11 ]

23 голосов
/ 30 апреля 2010

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

6 голосов
/ 10 февраля 2013

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

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

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

Или перед нажатием в UIViewController установите значение hidesBottomBarWhenPhed:

viewControllerWithNoToolBar.hidesBottomBarWhenPushed = YES
[self.navigationController pushViewController:viewControllerWithNoToolBar animated:YES];
6 голосов
/ 25 января 2012

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

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

Вот что я сделал. Я не знаю, являются ли протоколы маркеров идиоматическими объектами-c или нет, но я сравниваю их с атрибутами, которые я использовал бы в 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;

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

1 голос
/ 18 января 2012

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

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

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

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

1 голос
/ 13 апреля 2011

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

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

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

1 голос
/ 13 октября 2010

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

В следующем коде предполагается, что secondController помещается в представление навигации с помощью действия, выполняемого в 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 - это просто вспомогательный метод:

AppDelegate_Shared.m

+ (AppDelegate_Shared*)sharedDelegate {
    return (AppDelegate_Shared*)[[UIApplication sharedApplication] delegate];
}
0 голосов
/ 01 июля 2015

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

Мне удалось выполнить это правило:

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

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

0 голосов
/ 25 февраля 2013

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

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

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

- (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! - /1764074/skrytie-uitoolbar-uinavigationcontroller-vo-vremya-prosmotra-ischeznet
    [self.navigationController setToolbarHidden:YES animated:YES];
.
.
.
}
0 голосов
/ 30 июня 2012

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

self.navigationController.toolbar.barStyle = UIBarStyleBlackTranslucent;

в viewDidLoad.

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

0 голосов
/ 26 мая 2010

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

Определите этот (приватный) ивар в интерфейсе 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.

...