Xcode 6 - Swift - 自定义带导航的选项卡栏

6
我正在尝试使用Swift/XCode 6.2创建一个带有选项卡的应用程序,其中包含选项卡栏内的导航元素,如下图所示(红色栏)。基本上,中间的三个图标将引导用户进入不同的视图控制器。其他两个图标将是基于上下文的。例如,在表视图页面上,您将看到菜单图标和添加新图标,如图像所示。但是,单击行会将菜单图标更改为返回图标,将添加图标更改为其他内容。
这是大致的想法,但我很难实现接近这个的东西。第一个问题是,每当我在Tab Bar Controller中嵌入一个视图时,我就无法将选项卡栏移动到顶部。但是,当我在View Controller中创建自定义UITabView时,Control + 单击并将Tab Bar Item拖动到另一个视图不会创建segue。我甚至还没有开始处理栏内的导航元素。
我想问的只是关于采取什么路线来解决这个问题的一些指导。我假设我不能使用Tab Bar Controller或Navigation Controller,因为它们似乎不能太多地自定义。因此,自定义选项卡栏和导航栏,然后以编程方式实现segue和按钮更改?
谢谢。
2个回答

12
我将从架构角度为您提供指导(因此下面的内容不会涉及太多代码)。

使用UITabBarController

为了实现您所建议的功能,您是正确的不能直接使用UITabBarController,其中最直接的原因之一是它们始终应该在底部,而您想要它在顶部(请查看Apple's docs)。好消息是,您可能并不需要它! 注意:如果出于任何原因仍然想使用UITabBarController,请参见@Matt的answer

使用UINavigationController

您可以使用UINavigationController来解决此任务,因为UINavigationControllerUINavigationBar可以进行自定义。有多种方法可以组织视图层次结构以实现您的目标,但让我详细说明一种选项:
  1. To customize a UINavigationBar's to add buttons, you just need to set its navigationItem's title view:

    // Assuming viewWithTopButtons is a view containing the 3 top buttons
    self.navigationItem.titleView = viewWithTopButtons
    
  2. To add the burger menu functionality on a UINavigationController you can find several posts on how to do it and infinite frameworks you can use. Check this other SO Question for a more detailed answer (e.g. MMDrawerController, ECSlidingViewController to mention a couple).

  3. About organizing your view hierarchy, it really depends on if when the user taps one of the main top buttons, it will always go to the first view controller in the new section or if you want to bring him back to the last view in the section where he was.

    3.1 Switching sections displays the first view of the new section

    Your app's UIWindow will have a single UINavigationController on top of the hierarchy. Then each of the 3 top buttons, when tapped, will change the root view controller of the UINavigationController.

    Then, when the user changes section, the current navigation hierarchy is discarded by setting the new section view controller as the UINavigationController root view controller.

    self.navigationController = [sectionFirstViewController]
    

    3.2 Switching sections displays the last displayed view in the new section

    This will require a slightly modified version of the above, where your each of your sections will have its own UINavigationController, so you can always keep a navigation hierarchy per section.

    Then, when the user taps one of the top buttons to switch section, instead of changing as previously described, you will change the UIWindowroot view controller to the new section's UINavigationController.

    window.rootViewController = sectionNavigationController
    

使用自定义实现

当然,最后也是非常有效的选择就是你自己实现组件以达到你的要求。这可能需要最大的努力,但也能够获得最高的可定制性。

建议不具备足够经验的开发人员不要选择此选项。


我应该在哪里设置我的titleView属性?如果我在与故事板导航控制器相关的自定义NavigationController中设置它,那么titleView就不会显示出来。如果我在3个主要的视图控制器之一中设置它,那么它可以工作,但这是否意味着我需要三次初始化自定义的titleView呢? - Ryan Bobrowski
1
你不需要每次都初始化自定义视图,只需要初始化一次,然后在每个UIViewController中将其分配为“titleView”。如果不使用某种外观设置,我想不出其他方法。无论如何,值得看一下“UINavigationController”文档的“更新导航栏”部分,可能会给你一些想法。 - veducm

3
我愿意尝试一下——我认为可以在此处使用选项卡栏控制器。
  • 您的顶层视图控制器将是带有隐藏选项卡栏的UITabBarController
  • 每个选项卡都包含在UINavigationController中。
  • 导航控制器中的所有视图控制器都将是视图控制器(比如,SwitchableViewController)的子类。
  • SwitchableViewControllerviewDidLoad中,您将导航项的标题视图(即位于中心的任何内容;self.navigationItem.titleView)设置为包含三个中心按钮的视图。可以是UISegmentedControl或自定义视图。
  • 每当您点击任何按钮时,都会将顶部的UITabBarController的选定索引更改为要显示的视图控制器。

可能遇到的问题:

  • 选项卡内部的表视图将具有底部的scrollIndicatorOffset,即使选项卡栏被隐藏。
  • 每次在导航堆栈中推入新的视图控制器时,您的标题视图都将进行动画处理。
    • 解决方案:查看为UINavigationController创建自定义转换动画。

我不确定拥有一个隐藏的 UITabBarController 来有效地更改窗口的根视图控制器是否有益处。但是,我仍然认为这是一种有趣的方法,我想问问你,尽管我知道这意味着不会增加你的声誉,但出于完整性的考虑,您是否考虑编辑我的答案以添加此选项。 - veducm
啊,但是 UITabBarController 在这里是窗口的根视图控制器。 - Matthew Quiros
是的,我理解这一点,但我想说的是,你使用它的唯一原因是要更改窗口的根视图控制器...如果没有UITabBarController,你也可以直接在UIWindow中完成这个操作,不是吗? - veducm
使用 UITabBarController,您可以为每个选项卡提供独立的导航堆栈。titleView 按钮显然作为选项卡功能,并且在 iOS 的设计语言中,即使您切换它们,每个选项卡的导航堆栈也会被保留。您的方法每次进行选择时都会丢弃当前的导航堆栈。这是 @itstrueimryan 想要的吗?我不知道。我们两个都没有看到他的应用程序的完整规格。我只是给他另一个选项。 - Matthew Quiros
我同意,并且正如我所说,我认为这是一种有趣的方法。如果您同意的话,我将在我的答案中提到它,在UITabBarController部分。 - veducm

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