选项卡栏控制器位于导航控制器内,或共享导航根视图

时间:2009-02-23 07:10:26

标签: iphone cocoa-touch uitabbarcontroller uinavigationbar

我正在尝试实现类似于 Tweetie 应用程序的UI,其行为如下:顶级视图控制器似乎是导航控制器,其根视图是“帐户” “表视图。如果您点击任何帐户,它将转到第二级,其底部有一个标签栏。每个选项卡项都显示不同的列表,并允许您进一步向下钻取(后续级别不显示选项卡栏)。

因此,这似乎是实现层次结构:

  • UINavigationController
    1. 帐户UITableViewController
    2. UITabBarController
      1. 推文UITableViewController
        • 推文/用户/等的详细信息视图
      2. 回复UITableViewController
      3. ...

这似乎有效[^ 1],但根据-pushViewController:animated:的SDK文档(强调添加)似乎不受支持:

  

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

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

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

我该如何以正确的方式实现这一目标?

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

9 个答案:

答案 0 :(得分:63)

之前的两个答案是对的 - 我没有在Tweetie中使用UITabBarController。编写一个自定义XXTabBarControllerUIViewController的简单子类)很容易被推到导航控制器堆栈上,但仍然遵循“视图控制器”的理念。帐户特定视图(Tweets / Replies / Messages)上的每个“标签”都是自己的视图控制器,就他们而言,他们会在屏幕上交换通过简单的UITabBarController

答案 1 :(得分:34)

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

答案 2 :(得分:10)

可以将UITabBar添加到任何UIViewController。这样你实际上不必推送UITabBarController,因此保持在Apple API的指导范围内。

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

答案 3 :(得分:9)

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

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

答案 4 :(得分:6)

我在过去一小时内一直在努力实施UITabBar,因为当我试图展示我的观点时它会被隐藏起来;然后我找到了post

基本上,请确保按照以下代码行在标签栏下方插入新视图:

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

答案 5 :(得分:3)

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

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

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

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

appDelegate.window.rootViewController = myNavControllerInstance;

答案 6 :(得分:3)

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

如果这是事实,苹果是否可能拒绝将我的应用发布到appstore?

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

答案 7 :(得分:2)

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

  1. 拖动ViewController
  2. 单击ViewController的场景
  3. 点击编辑器>>嵌入>>导航控制器。
  4. 拖动同一ViewController上的按钮。
  5. 拖动TabBarController
  6. 通过推送Segue Action将ViewController上的按钮连接到TabBarController。
  7. 在这种情况下,只有TabBarController的RootViewController将位于导航控制器的堆栈中。所有TabBarItems都会在顶部显示导航栏,用户可以随时进入主屏幕,无论选择的TabBarItem如何

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

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

答案 8 :(得分:1)

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

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