选项卡控制器在导航控制器内部,或共享导航根视图。

80

我正在尝试实现一个类似于 Tweetie 应用的 UI 结构,其行为如下:顶级视图控制器似乎是一个导航控制器,其根视图是 "账户" 表视图。如果点击任何帐户,它将进入第二层,这里有一个底部的选项卡栏。每个选项卡项目显示不同的列表,并允许您进一步深入(随后的级别不显示选项卡栏)。

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

  • UINavigationController
    1. Accounts: UITableViewController
    2. UITabBarController
      1. Tweets: UITableViewController
        • 推文/用户等的详细信息视图
      2. Replies: UITableViewController
      3. ...

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

  

viewController:要推到堆栈上的视图控制器。它不能是选项卡栏控制器的实例。

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

我考虑过将选项卡栏控制器作为主控制器,并让每个选项卡包含单独的导航控制器。问题在于,每个导航控制器都需要共享一个根视图控制器(即 Tweetie 中的 "账户" 表)- 这似乎不起作用:将表控制器推到第二个导航控制器似乎会将其从第一个导航控制器中删除。更不用说当选择不同的帐户时所有的记账工作可能会很麻烦。

应该如何正确地实现这个功能?

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

9个回答

63
两个之前的答案都是正确的 - 我在Tweetie中没有使用UITabBarController。很容易编写一个定制的XXTabBarController(继承自UIViewController的子类),它可以愉快地被推送到导航控制器堆栈中,但仍然遵循“视图控制器”哲学。账户特定视图 (Tweets/Replies/Messages) 上的每个“标签页”都是它自己的视图控制器,并且只要它们认为自己在屏幕上被普通的 UITabBarController 切换就可以了。

2
你的自定义标签栏控制器类如何处理其子控制器的navigationItem和navigationController属性的基本设置? - bvanderveen
iOS 5有所改变吗?我似乎可以将UITabBarController轻松添加到UINavigationController中,即使作为根控制器也没有太大问题。 - sparkFinder

33

我正在开发一个应用程序,它使用与Tweetie类似的导航框架。 我在我的博客www.wiredbob.com上撰写了一篇有关如何实现此功能的文章,该文章还链接到源代码。 这是一个完整的模板,你可以采用它作为另一个项目的基础。 祝好运!


10
对于那些想知道的人,提到的博客文章链接是http://www.wiredbob.com/blog/2009/4/20/iphone-tweetie-style-navigation-framework.html。 - Anh
@Robert Conn,非常棒的教程。我正在使用你的概念,但出现了一些问题,我的 tabBar 不起作用。在您实施应用程序时是否出现了这种情况? - A Salcedo
2
这篇博客对我来说已经过时了,有人还留着吗? - Tiago Veloso
工作博客文章链接:http://www.wiredbob.com/2009/04/iphone-tweetie-style-navigation.html - oluckyman
你不应该链接到外部资源来回答问题。相反,你应该在这里提供答案,并引用外部资源以获取更深入的信息。 - Koen.

10

可以将UITabBar添加到任何UIViewController中。这样,您实际上不需要推出UITabBarController,因此可以遵循Apple API的指南。

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


1
你好!@Himadri Choudhury,你能解释一下“因此遵守Apple API的指南”吗?或者给出参考资料?我找不到这个指南在哪里被提到(我不怀疑它的存在,但我找不到URL)。非常感谢。 - darksider

10

我在我的一些应用程序中这样做。将选项卡栏添加到基于导航控制器的应用程序的技巧是不要使用TabBarController。将选项卡栏添加到视图中,使该视图控制器成为TabBarDelegate,并在该视图控制器的代码中响应用户对选项卡的选择。

我使用选项卡栏将其他视图作为子视图添加到选项卡栏的视图中,重新加载具有不同数据集的表视图,重新加载UIPickerView等。


6

过去一小时我一直在苦苦挣扎地尝试实现一个UITabBar,因为当我尝试显示我的视图时它会被隐藏; 后来我发现了这个帖子:

基本上,确保你将你的新视图插入到选项卡栏下面,使用以下代码行:

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

谢谢,这有助于修复我的标签栏消失问题。我使用了 Robert Conn 建议的相同代码,但是当我切换到第二个视图时,UI 标签栏不知何故消失了。 - Vijay Katam

3
在我的应用程序中,根视图控制器是一个UINavigation控制器。在应用程序的某个特定点上,我需要显示一个UITabBar。我尝试在导航层次结构中的UIView上实现UITabBar,正如一些先前的帖子所建议的那样,这确实可以工作。但我发现我想要更多的选项卡控制器提供的默认行为,并找到了一种使用UITabBarController与UINavigation控制器的方法:
1)当我想要显示UITabBarController的视图时,我这样做:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;

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

appDelegate.window.rootViewController = myNavControllerInstance;

3
这是我这样做的方式。实际上,这是将tabbarcontroller推到navigation controller上。它可以正常工作。我没有在文档中找到苹果不支持这种方式的任何地方。有人能给我一个链接来警告吗?
如果这是真的,苹果会拒绝将我的应用程序发布到应用商店吗?
-(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了。 - Gargo

3
这可以通过简单地将TabBarController嵌入到Navigation Controller中来实现。 在Storyboard中:
  1. 拖动一个ViewController
  2. 点击ViewController的场景
  3. 点击编辑器 >> 嵌入 >> Navigation Controller。
  4. 在同一个ViewController上拖动一个按钮。
  5. 拖动一个TabBarController
  6. 通过push Segue Action将ViewController上的按钮连接到TabBarController。
在这种情况下,只有TabBarController的RootViewController会在Navigation Controller的堆栈中。所有的TabBarItems都会在顶部有导航栏,用户可以随时回到主屏幕,而不管选择了哪个TabBarItem。
这可以在Navigation Controller的堆栈中的任何ViewController中完成。
如果有效,请建议如何增加声誉,以便我可以在下一个答案中发布图像和代码。 :)

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接