导航控制器内的标签栏控制器,或共享导航根视图

Posted

技术标签:

【中文标题】导航控制器内的标签栏控制器,或共享导航根视图【英文标题】:Tab bar controller inside a navigation controller, or sharing a navigation root view 【发布时间】:2010-10-09 06:31:44 【问题描述】:

我正在尝试实现类似于 Tweetie 应用程序中的 UI 结构,其行为如下:***视图控制器似乎是导航控制器,其根视图是“帐户" 表视图。如果您单击任何帐户,它会进入第二级,底部有一个标签栏。每个选项卡项显示一个不同的列表,让您可以进一步向下钻取(后续级别不显示选项卡栏)。

所以,这似乎是实现层次结构:

UINavigationController
    帐户UITableViewController UITabBarController
      推文UITableViewController 推文/用户/等的详细视图 回复UITableViewController ...

这似乎可行[^1],但根据 -pushViewController:animated: 的 SDK 文档似乎不受支持(已添加重点):

viewController:被压入堆栈的视图控制器。 不能是标签栏控制器的实例。

我想避免使用私有 API 等,但我不确定为什么即使这种用法似乎工作正常,也会被明确禁止。有人知道原因吗?

我考虑过将标签栏控制器作为主控制器,每个标签都包含单独的导航控制器。这样做的问题是每个导航控制器都需要共享一个根视图控制器(即 Tweetie 中的“Accounts”表)——这似乎不起作用:将表控制器推送到第二个导航控制器似乎将其从第一个中删除。更不用说在选择其他帐户时进行所有记账可能会很痛苦。

我应该如何以正确的方式实现它?

[^1]:标签栏控制器需要被子类化,以便标签栏控制器在该级别的导航项与所选标签的导航项保持同步,并且单个标签的表格控制器需要推送各自的详细视图到self.tabBarController.navigationController 而不是self.navigationController

【问题讨论】:

【参考方案1】:

前两个答案是正确的 - 我在 Tweetie 中不使用 UITabBarController。编写自定义XXTabBarControllerUIViewController 的普通子类)非常容易,它很高兴被推入导航控制器堆栈,但仍然遵循“视图控制器”理念。帐户特定视图 (Tweets/Replies/Messages) 上的每个“选项卡”都是它自己的视图控制器,就他们而言,它们正在被普通的@ 987654327@.

【讨论】:

您的自定义标签栏控制器类如何处理其子控制器的 navigationItem 和 navigationController 属性的管道? 这在 ios 5 中有改变吗?我似乎能够将 UITabBarController 添加到 UINavigationController 中而没有太多问题,即使作为根控制器也是如此。【参考方案2】:

我正在构建一个使用与 Tweetie 类似的导航框架的应用。我在我的博客www.wiredbob.com 上写了一篇关于如何做到这一点的帖子,该帖子还链接到源代码。这是一个完整的模板,您可以将其用作另一个项目的基础。祝你好运!

【讨论】:

对于那些想知道的人,提到的博客文章的链接是wiredbob.com/blog/2009/4/20/… @Robert Conn,非常好的教程。我正在使用您的概念,但由于某种原因,我的 tabBar 未激活。您在实施应用时是否遇到过这种情况? @ASalcedo:我也有这个问题,但发现是因为我需要减小与标签栏项目关联的视图的大小,默认的高度大小460太大了,在www.wiredbob.com 上的源代码,您将看到为选项卡项设置的高度为 369,以允许选项卡栏。为了在界面生成器中更改高度,您还必须确保视图的属性检查器中的状态、顶部和底部栏都设置为无(不是很明显)。 这篇博文对我来说已经死了,有没有可能有人把它放在身边? 工作博客文章链接:wiredbob.com/2009/04/iphone-tweetie-style-navigation.html【参考方案3】:

可以将 UITabBar 添加到任何 UIViewController。这样一来,您实际上就不必推送 UITabBarController,从而保持在 Apple API 的指导范围内。

在界面构建器中,UITabBar 位于 Cocoa Touch Library 中的“Windows、Views & Bars”下。

【讨论】:

嗨! @Himadri Choudhury 你能解释一下“并因此遵守 Apple API 的指导方针” - 或提供参考吗?我找不到该指南在哪里被告知(我不怀疑它存在,但我找不到 URL)。非常感谢【参考方案4】:

我在我的几个应用程序中执行此操作。将标签栏添加到基于 navigationController 的应用程序的技巧是不使用 TabBarController。在视图中添加一个 Tab Bar,使该视图的视图控制器成为 TabBarDelegate,并在视图控制器的代码中响应用户在标签栏上的选择。

我使用 Tab Bars 将其他视图添加到 Tab Bar 的视图中作为子视图、重新加载具有不同数据集的表格视图、重新加载 UIPickerView 等。

【讨论】:

【参考方案5】:

在过去的一个小时里,我一直在努力实现UITabBar,因为当我尝试显示我的视图时它会被隐藏;然后我发现了这个post:

基本上,请确保根据这行代码在标签栏下方插入新视图:

[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];

【讨论】:

感谢这有助于修复我消失的标签栏。我使用了 Robert Conn 提出的相同代码,但不知何故,当我切换到第二个视图时,ui 标签栏消失了。【参考方案6】:

在我的应用程序中,根视图控制器是 UINavigation 控制器。在应用程序的某个时刻,我需要显示一个 UITabBar。正如之前的一些帖子所建议的那样,我尝试在导航层次结构中的 UIView 上实现 UITabBar,这确实有效。但是我发现我想要更多选项卡控制器提供的默认行为,并且我找到了一种将 UITabBarController 与 UINavigation 控制器一起使用的方法:

1) 当我想显示 UITabBarController 的视图时,我这样做:

MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;

2) 当我想返回到我在导航层次结构中的位置时,我会这样做:

appDelegate.window.rootViewController = myNavControllerInstance;

【讨论】:

【参考方案7】:

这可以通过简单地将 TabBarController 嵌入到导航控制器中来实现。 在故事板中:

    拖一个 ViewController 点击 ViewController 的场景 点击编辑器>>嵌入>>导航控制器。 在同一个 ViewController 上拖动一个按钮。 拖动一个 TabBarController 通过 push Segue Action 将 ViewController 上的按钮连接到 TabBarController。

在这种情况下,只有 TabBarController 的 RootViewController 会在导航控制器的堆栈中。所有的 TabBarItems 都会在顶部有导航栏,用户可以随时进入主屏幕,无论选择的 TabBarItem 是什么

这可以在导航控制器堆栈中的任何 ViewController 上完成。

如果可行,请建议我如何提高声誉,以便我可以在下一个答案中发布图像和代码。 :)

【讨论】:

【参考方案8】:

我就是这样做的。这实际上是将 tabbarcontroller 推到导航控制器上。它工作正常。我在文档中没有找到苹果不支持这种方式的任何地方。谁能给我这个警告的链接?

如果这是真的,苹果是否有可能拒绝将我的应用发布到应用商店?

-(void)setArrayAndPushNextController

    MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
    MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];

    myFirstViewController.array = self.array;


    NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
    UITabBarController *tab = [[UITabBarController alloc] init];
    tab.viewControllers = array;

    [array release];

    UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:@"first title" image:nil tag:1];
    UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:@"second title" image:nil tag:2];

    myFirstViewController.tabBarItem = item1;
    mySecondViewController.tabBarItem = item2;

    [self stopAnimatingSpinner];

    [self.navigationController pushViewController:tab animated:YES];

    [tab release];
    [item1 release];
    [item2 release];

【讨论】:

你忘了释放你的 UIViewControllers【参考方案9】:

我写了一篇关于我如何解决这个问题的博客文章。对我来说,使用模态视图比编写自定义标签栏实现更简单。

http://www.alexmedearis.com/uitabbarcontroller-inside-a-uinavigationcontroller/

【讨论】:

以上是关于导航控制器内的标签栏控制器,或共享导航根视图的主要内容,如果未能解决你的问题,请参考以下文章

呈现一个导航栏和一个非根视图标签栏控制器

当以编程方式设置根视图控制器时,导航和标签栏丢失

以编程方式导航到另一个故事板上的导航控制器和标签栏控制器内的视图控制器

标签栏控制器内的导航控制器不显示标题

以编程方式创建 UINavigationController

Swift 2:更改与选项卡栏控制器相关的视图上的导航标题