【问题标题】:Swift: UITabBar with a sharing header on all screensSwift:UITabBar 在所有屏幕上都有一个共享标题
【发布时间】:2017-06-15 21:53:19
【问题描述】:

我现在正在尝试基于 UITabBar 构建一个应用程序。我的 TabBar 应该只更改屏幕上的一个区域,而不是整个屏幕。这就是我不使用 UITabBarController 的原因。

因此,如果我现在在 UIViewController 上添加一个 UITabBar,我不知道如何告诉我的选项卡它们必须将哪个 View 更改为哪个 ViewController。

这也是我的意思的图片。在图片上,我希望始终使用棕色背景和标签。 UIView 是我想用标签栏项目更改视图控制器视图 1 和 2 的部分。那可能吗?

【问题讨论】:

标签: swift


【解决方案1】:

我举了一个例子来说明我认为你正在努力实现的目标。点击标签栏按钮会在黄色视图中显示其各自的视图控制器。

首先在Interface Builder中排列三个视图控制器,如上图。将一个普通的UIView(不是容器视图)拖到主视图控制器上并定位它(根据需要使用约束)。在下面添加标签栏(设置其代表)和标签,如图所示。

然后按住 Control 并拖动以创建从主视图控制器到每个子视图控制器的 segue。当弹出窗口选择 segue 类型时,选择自定义

然后单击每个 segue 连接并在 Attributes Inspector 中为每个连接指定一个标识符(例如 firstsecond),并将它们的类设置为 MySegue(我们将很快创建一个自定义 segue):

假设主视图控制器设置为 ViewController 类,请将 ViewController.swift 替换为以下内容:

class MySegue: UIStoryboardSegue {
    override func perform() {
        // Leave empty (we override prepareForSegue)
    }
}

class ViewController: UIViewController, UITabBarDelegate {

    @IBOutlet weak var containerView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load the first screen by default.
        performSegue(withIdentifier: "first", sender: nil)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue is MySegue {

            // This is an example of how to use the UIViewController containment APIs.
            // If we're starting, there is not yet a child view controller added, so
            // just add it.
            if childViewControllers.count == 0 {

                self.addChildViewController(segue.destination)
                segue.destination.view.frame = containerView.bounds
                self.containerView.addSubview(segue.destination.view)
                segue.destination.didMove(toParentViewController: self)

            // If there is already a child, swap it with the segue's destination view controller.
            } else {

                let oldViewController = self.childViewControllers[0]
                segue.destination.view.frame = oldViewController.view.frame
                oldViewController.willMove(toParentViewController: nil)
                self.addChildViewController(segue.destination)
                self.transition(from: oldViewController, to: segue.destination, duration: 0, options: .transitionCrossDissolve, animations: nil) { completed in
                    oldViewController.removeFromParentViewController()
                    segue.destination.didMove(toParentViewController: self)
                }
            }
        }
    }

    func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let index = tabBar.items?.index(of: item) else { return }
        switch index {
        case 0:
            performSegue(withIdentifier: "first", sender: nil)
        case 1:
            performSegue(withIdentifier: "second", sender: nil)
        default:
            break
        }
    }
}

现在将containerView 的 IBOutlet 连接到主视图控制器的黄色视图。

编译并观察点击标签栏按钮如何在黄色视图内的两个视图控制器之间切换,保持上面的共享标签。

这是 UIViewController 包含 API 的示例。

【讨论】:

  • 这听起来像是我想要的。但是,如果我正在实现您的代码,那么 ViewController 会尝试调用 performSegue 我得到以下错误:'无法创建类'(null)'的segue。而且我从不准备(正因为如此。
  • 太棒了,我可以在答案中添加任何内容以使其更清晰吗?
  • 是的。此时我需要多做一步:然后单击每个 segue 连接并在 Attributes Inspector 中,为每个连接指定一个标识符(例如 first 和 second),将它们的类设置为 MySegue(我们将很快创建一个自定义 segue)并设置模块到您的项目名称:
  • @paulvs 您的解决方案太棒了,您只是忘记将 UITabBar 的 IBOutlet 连接到 viewController 并在 viewDidLoad()set 上将其委托给 self。此外,动画应根据索引位置绘制,因此滑动是从左到右或相反的天气。
猜你喜欢
  • 2021-12-18
  • 2013-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
相关资源
最近更新 更多