【问题标题】:How to anchor a tabbed ViewController to the top of the TabBar at the bottom of the screen programatically?如何以编程方式将选项卡式 ViewController 锚定到屏幕底部的 TabBar 顶部?
【发布时间】:2021-02-12 05:36:45
【问题描述】:

我有一个单屏 ios 应用程序,我想添加第二个选项卡,所以我创建了一个单独的类 TabBarController 并将我的原始应用程序屏幕和一个新屏幕作为两个选项卡。

它工作正常,除了在我的单屏应用程序中,我在页面底部有一个元素锚定到安全区域,现在它被标签栏部分覆盖:

我正在以编程方式创建所有内容(我不擅长使用 UI,我忘记了所有内容在哪里)。

如何以编程方式将底部元素锚定到标签栏的顶部,而不是屏幕底部?我需要获取标签栏的引用,但是如何在子控制器中获取呢?

非常感谢!

编辑:

这是我原来的锚:

stackView.bottomAnchor.constraint(
            equalTo: self.view.safeAreaLayoutGuide.bottomAnchor,
            constant: VIEW_SPACER).isActive = true

现在我正在尝试:

 stackView.bottomAnchor.constraint(
            equalTo: self.tabBarController!.tabBar.topAnchor,
            constant: VIEW_SPACER).isActive = true

我不明白我的子控制器如何引用 tabBarController,但显然它确实如此。但是使用它会导致崩溃。错误信息似乎是:

'Unable to activate constraint with anchors ... because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.

编辑2: 我设置控制器的方式:

class TabBarController: UITabBarController, UITabBarControllerDelegate {
...
   override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let firstViewController = ViewController()
        let secondViewController = SettingsViewController()
        let tabBarList = [firstViewController, secondViewController]
        
        viewControllers = tabBarList
   }

然后我将 TabBarController 设置为情节提要中的元素,以作为 root 实例化。

【问题讨论】:

  • 请显示你做了什么,你可能没有从safeArea底部添加约束。
  • 谢谢@Rob。我已经添加了我的旧代码和我正在尝试的内容
  • 当您没有将当前组件添加到subview时会出现此错误。
  • 哦等等。那个 VIEW_SPACER 应该在我的元素和底部之间放置一个间隙,但是我弄错了,不是吗?我正在添加 Y 值而不是从中减去。这不是我第一次这样做。谢谢@Rob,你给我指出了正确的地方。我已经改了,现在很好..
  • @Rob 我还是很好奇。我的子 ViewController 是如何引用 TabBar 的?

标签: ios swift autolayout


【解决方案1】:

对于您的底部约束,您需要从控制器的view.safeAreaLayoutGuide.bottomAnchor 执行此操作。您不应在视图控制器中使用来自 tabBar 控制器的任何约束,因为控制器并不总是位于 tabBarController 的视图层次结构中。此外,由于您正在设置相对于视图控制器的 stackView 的底部约束,因此要高于控制器的底部锚点,该值需要为负数。

当控制器被添加到 UINavigationControllerUITabBarController 的视图层次结构中时,它们会在控制器上设置相应的属性(self.navigationControllerself.tabBarController),以便它可以访问它的父控制器。

class TabBarController: UITabBarController, UITabBarControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let firstViewController = ViewController()
        firstViewController.title = "First"

        let secondViewController = SettingsViewController()
        secondViewController.title = "Second"

        let tabBarList = [firstViewController, secondViewController]

        setViewControllers(tabBarList, animated: false)
    }
}

class ViewController: UIViewController {

    let stackView = UIStackView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(stackView)

        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.backgroundColor = .red

        stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        stackView.heightAnchor.constraint(equalToConstant: 150).isActive = true
        stackView.bottomAnchor.constraint(
            equalTo: view.safeAreaLayoutGuide.bottomAnchor,
            constant: -5).isActive = true
    }
}

class SettingsViewController: UIViewController {

    let stackView = UIStackView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(stackView)

        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.backgroundColor = .blue

        stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        stackView.heightAnchor.constraint(equalToConstant: 150).isActive = true
        stackView.bottomAnchor.constraint(
            equalTo: view.safeAreaLayoutGuide.bottomAnchor,
            constant: -1).isActive = true
    }
}

【讨论】:

    猜你喜欢
    • 2020-08-17
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    相关资源
    最近更新 更多