【问题标题】:Centering between two anchors在两个锚点之间居中
【发布时间】:2019-05-23 22:07:52
【问题描述】:

我想在两个锚点之间设置一个centerYAnchor。类似这样:

centeredLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),

但是,我不希望它相对于屏幕居中。我希望它位于屏幕上其他两个锚点之间。就像我在顶部有一个这样的工具栏:

toolbar.topAnchor.constraint(equalTo: view.topAnchor),

然后我在底部有一个这样的按钮:

button.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: -20)

有没有办法让centeredLabel 的 y 约束位于toolbar 的底部锚点和button 的顶部锚点之间?

【问题讨论】:

    标签: ios swift autolayout anchor


    【解决方案1】:

    有没有一种方法可以将 centeredLabel 的 y 约束居中在工具栏的底部锚点和按钮的顶部锚点之间?

    是的,有。简单的方法是使用透明的间隔视图,其顶部锚定到上锚,底部锚定到下锚。现在您将标签中心锚定到间隔视图的中心。

    然而,虽然这很简单,但这并不是最好的方式。最好的方法是创建自定义UILayoutGuide,而不是透明的间隔视图。不幸的是,这只能在代码中完成,而不是在情节提要中(而间隔视图和标签可以完全在情节提要中配置)。但它的优点是它不会为渲染树增加额外的视图。

    这是您的情况,或多或少,使用按钮作为上视图,使用按钮作为下视图。标签在它们之间垂直居中:

    这是产生这种情况的代码。 b1b2 是按钮(不管它们是如何创建和定位的):

        let g = UILayoutGuide()
        self.view.addLayoutGuide(g)
        g.topAnchor.constraint(equalTo: b1.bottomAnchor).isActive = true
        g.bottomAnchor.constraint(equalTo: b2.topAnchor).isActive = true
        g.leadingAnchor.constraint(equalTo:b1.leadingAnchor).isActive = true
        g.trailingAnchor.constraint(equalTo:b1.trailingAnchor).isActive = true
        let lab = UILabel()
        lab.text = "Label"
        lab.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(lab)
        lab.leadingAnchor.constraint(equalTo:g.leadingAnchor).isActive = true
        lab.centerYAnchor.constraint(equalTo:g.centerYAnchor).isActive = true
    

    【讨论】:

    • 酷!我将详细向您展示情节提要解决方案,但您会发现 UILayoutGuide 正是您要寻找的。它是一组没有实际视图的类似视图的锚点。正如文档所说,“使用布局指南替换您可能创建的虚拟视图,以表示视图间空间或用户界面中的封装。”这正是你所拥有的,一个“采访空间”。
    • 您如何看待将视图放在堆栈视图中并在具有视图的堆栈上方和下方放置一个堆栈?然后将底部堆栈设置为与顶部堆栈的高度相等以居中?那也不错吗?还是布局指南更好?
    【解决方案2】:

    虽然@matt 的解决方案有效,但这里有一个更简单的解决方案,它使用自动布局而不需要创建 UILayoutGuide。

    iOS 10 通过NSLayoutXAxisAnchor.anchorWithOffset(to:)NSLayoutYAxisAnchor.anchorWithOffset(to:) 引入了一种简单的方法。

    这里是包装这个逻辑的便捷方法。

    X轴定心

    extension NSLayoutXAxisAnchor {
        func constraint(between anchor1: NSLayoutXAxisAnchor, and anchor2: NSLayoutXAxisAnchor) -> NSLayoutConstraint {
            let anchor1Constraint = anchor1.anchorWithOffset(to: self)
            let anchor2Constraint = anchorWithOffset(to: anchor2)
            return anchor1Constraint.constraint(equalTo: anchor2Constraint)
        }
    }
    

    Y轴定心

    extension NSLayoutYAxisAnchor {
        func constraint(between anchor1: NSLayoutYAxisAnchor, and anchor2: NSLayoutYAxisAnchor) -> NSLayoutConstraint {
            let anchor1Constraint = anchor1.anchorWithOffset(to: self)
            let anchor2Constraint = anchorWithOffset(to: anchor2)
            return anchor1Constraint.constraint(equalTo: anchor2Constraint)
        }
    }
    

    做你需要的,你可以打电话:

    centeredLabel.centerYAnchor.constraint(between: toolbar.bottomAnchor, and: button.topAnchor)
    

    【讨论】:

      猜你喜欢
      • 2013-04-04
      • 2014-08-09
      • 2017-07-28
      • 1970-01-01
      • 2020-01-12
      • 2018-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      相关资源
      最近更新 更多