iPhone: Показати модальний UITableViewController за допомогою панелі навігації


87

Я демонструю модальний вигляд, який є UITableViewControllerкласом. Чомусь він не відображатиме панель навігації, коли я її показую. Ось мій код:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
    detailViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    detailViewController.navigationController.navigationBarHidden = NO;
    [self.navigationController presentModalViewController:detailViewController animated:YES];
    detailViewController = nil;
    [detailViewController release];

Я думав, це показано за замовчуванням? Якщо це допомагає, я телефоную з іншого класу, яким також UITableViewControllerкерує a UINavigationController. Ідеї?

Відповіді:


146

Коли ви представляєте модальний контролер перегляду, він не використовує жодних існуючих контролерів навігації або навігаційних панелей. Якщо все, що вам потрібно, це відображення панелі навігації, вам потрібно додати панель навігації як підпрогляд вашого модального подання та представити її так, як ви робите.

Якщо ви хочете представити модальний контролер подання з функцією навігації, вам потрібно представити модальний контролер навігації, що містить ваш контролер детального перегляду, замість цього:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[detailViewController release];

navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:navController animated:YES];
[navController release];

Ваш модальний контролер буде керувати власним стеком навігації.


Дякую, я ціную пояснення, тому я знаю, що я зробив неправильно.
Nic Hubbard,

1
Якщо ви використовуєте раскадровку, для цього не потрібне кодування. Хороше рішення!
Jelle

36

Ось один із способів відобразити панель навігації для тих, хто використовує розкадрування, запропонований підручником від Apple на Storyboard .

Оскільки модальний контролер подання не додається до стеку навігації, він не отримує навігаційну панель від контролера навігації контролера табличного подання. Щоб надати контролеру перегляду навігаційну панель, якщо вона представлена ​​в модальному вигляді, вбудуйте її у власний контролер навігації.

  1. У вікні структури виберіть Перегляд контролера.
  2. Вибравши контролер перегляду, виберіть Редактор> Вбудувати> Контролер навігації.

Переконайтеся, що ви додали модальний сегмент до Навігаційного контролера, а не TableViewController
bickster

У ситуації редагування сторінки профілю користувача Twitter. Це модально представлений UITableViewController, і він має кнопки ВИКОНАНО та СКАСУВАТИ вгорі. Ця відповідь не має сенсу в семантичному сенсі, оскільки навігація не відбувається.
Вільям Ентрікен

17

На iOS 7 і вам просто потрібна панель навігації на вашому модальному контролері перегляду, щоб показати заголовок та деякі кнопки? Спробуйте цю магію у своєму UITableViewController:

// in the .h
@property (strong) UINavigationBar* navigationBar;

//in the .m
- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"Awesome";
    self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
    [self.view addSubview:_navigationBar];
    [self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}

-(void)layoutNavigationBar{
    self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
    self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //no need to call super
    [self layoutNavigationBar];
}

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    [self layoutNavigationBar];
}

Шов - чудовий спосіб зробити щось. але коли я випробовую його на Static UITableViewController, я більше не можу прокручувати табличний перегляд. будь-яка ідея чому?
Thomas Besnehard

2
сьогодні вам було б краще вбудувати його в контролер навігації.
malhal

Це приємне рішення, але одна невелика проблема полягає в тому, що коли ви прокручуєте заголовки комірок, що відображаються вгорі на панелі навігації.
Алі

Я вирішив це, додавши [self.view bringSubviewToFront:self.navigationBar];в кінці -(void)layoutNavigationBar.
Алі

7

Я хочу поділитися, як прийняте рішення може бути використано в проектах з розкадровками:

Простий підхід полягає в тому, щоб поставити в розкадрування пустий контролер навігації перед VC, який повинен бути представлений модально, так що відносини виглядають так:

(Presenter VC) -> представляє модально -> (навігаційний контролер, контролер якого повинен бути представлений як його корінь).

Ми випробували цей підхід деякий час і помітили, що наші розкадровки "забруднюються" великою кількістю таких проміжних контролерів навігації, коли кожен! з них використовується виключно для одного! презентація якогось іншого контролера, який ми хочемо представити модально за допомогою панелі навігації.

Наше поточне рішення полягає в інкапсуляції коду від прийнятої відповіді до власної серії:

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

- (void)perform {
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.destinationViewController];

    [self.sourceViewController presentViewController:navigationController animated:YES completion:nil];
}
@end

Маючи цю секцію в нашому проекті, ми більше не створюємо проміжні контролери навігації на наших розкадровках, ми просто використовуємо цю ModalPresentationWithNavigationBarSegue, як:

VC для ведучого -> VC для ведучого

Я сподіваюся, що ця відповідь буде корисною людям, які люблять уникати непотрібного дублювання в раскадровках своїх додатків.


5

Якщо вам потрібен лише a NavigationBar, ви можете додати екземпляр UINavigationBarі призначити йому BarItems.


Це залежить від ViewController: я думаю, ви не можете додати UINavigationBar до UITableViewController, чи не так?
Тобіас,

У IB перейдіть до редактора -> Вбудувати в контролер навігації, і ви отримаєте панель навігації. Перетягніть і додайте BarButtonItems до цього.
AmitaiB

5

Я просто хотів додати щось до того, що сказав @Scott. Його відповідь - це, безумовно, найпростіший і найбільш прийнятний спосіб зробити це зараз за допомогою Storyboards, iOS 7 і 8 ... (а незабаром і 9).

Безумовно, додати контролер перегляду до Storyboard та вбудувати його, як описано @Scott, - це правильний шлях.

Потім просто додайте сегмент, перетягуючи керування з контролера джерела подання до цілі (тієї, яку ви хочете показати модально), виберіть «Представити модально», коли з’явиться маленький вид із вибором для типу сегмента. Можливо, добре також назвати це ім'я (у прикладі нижче я використовую "presentMyModalViewController").

Мені бракувало чогось, чого бракувало, - це випадок @ Scott, коли ви хочете фактично передати деякі дані тому модульно представленому контролеру перегляду, який вбудований в контролер навігації.

Якщо ви захопите segue.destinationViewController, це буде UINavigationController, а не контролер, який ви вбудували в UINavigationController.

Отже, щоб отримати вбудований контролер перегляду всередині навігаційного контролера, ось що я зробив:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"presentMyModalViewController"]) {
        // This could be collapsed, but it's a little easier to see
        // what's going on written out this way.

        // First get the destination view controller, which will be a UINavigationController
        UINavigationController *nvc = (UINavigationController *)segue.destinationViewController;

        // To get the view controller we're interested in, grab the navigation controller's "topViewController" property
        MyModalViewController *vc = (EmailReceiptViewController *)[nvc topViewController];

        // Now that we have the reference to our view controller, we can set its properties here:
        vc.myAwesomeProperty = @"awesome!";
    }
}

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.