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托管)调用此方法UINavigationController。有想法吗?

Answers:


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上的Tutorial建议,这是一种为正在使用Storyboard的用户显示导航栏的方法。

因为模式视图控制器不会添加到导航堆栈中,所以它不会从表视图控制器的导航控制器中获取导航栏。要为视图控制器提供模态显示时的导航栏,请将其嵌入自己的导航控制器中。

  1. 在大纲视图中,选择“视图控制器”。
  2. 选择视图控制器后,选择“编辑器”>“嵌入在”>“导航控制器”。

确保将模式选择添加到导航控制器,而不是TableViewController
bickster 2014年

在Twitter的“编辑用户个人资料”页面上。这是一个模态化的UITableViewController,它的顶部有DONE和CANCEL按钮。在这种情况下,此答案在语义上没有任何意义,因为没有导航发生。
William Entriken '16

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

接缝是做事情的好方法。但是当我在静态UITableViewController上进行尝试时,无法再滚动tableview。知道为什么吗?
Thomas Besnehard 2014年

2
如今,您最好将其嵌入导航控制器中。
malhal,2015年

这是一个不错的解决方案,但是一个小问题是,当您滚动显示在导航栏顶部的单元标题标题时。
阿里

我通过[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

在我们的项目中有了这个segue之后,我们就不再在故事板中创建中间导航控制器了,我们只需要像下面这样使用ModalPresentationWithNavigationBarSegue:

主持人VC->主持人VC

我希望这个答案对喜欢避免在应用程序故事板上进行不必要的重复的人有所帮助。


5

如果只需要一个NavigationBar,则可以添加的实例UINavigationBar并为其分配BarItems。


这取决于ViewController:我认为您不能将UINavigationBar添加到UITableViewController,可以吗?
Tobias

在IB中,转到“编辑器”->“嵌入导航控制器”,您将拥有一个导航栏。拖动并添加BarButtonItems。
AmitaiB '16

5

我只是想在@Scott所说的话中添加一些内容。他的答案无疑是现在使用Storyboards,iOS 7和8 ...(不久之后将是9)最简单,最被接受的方法。

正确地将视图控制器添加到情节提要中并按照@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!";
    }
}

希望这可以帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.