如何使用"自动布局视觉格式"?将两个视图放在同一位置?

时间:2016-07-16 10:31:01

标签: ios swift autolayout ios-autolayout

我想使用"自动布局视觉格式"将两个视图放在同一位置。在Swift中,我该如何以优雅的方式做到这一点?

我成功使用了NSLayoutConstraint,但我希望我仍然可以使用视觉格式找到一种优雅的方式。

我的代码使用NSLayoutConstraint:

NSLayoutConstraint(item: greenView, attribute: .Left, relatedBy: .Equal, toItem: redView, attribute: .Left, multiplier: 1.0, constant: 0).active = true
NSLayoutConstraint(item: greenView, attribute: .Top, relatedBy: .Equal, toItem: redView, attribute: .Top, multiplier: 1.0, constant: 0).active = true
NSLayoutConstraint(item: greenView, attribute: .Right, relatedBy: .Equal, toItem: redView, attribute: .Right, multiplier: 1.0, constant: 0).active = true
NSLayoutConstraint(item: greenView, attribute: .Bottom, relatedBy: .Equal, toItem: redView, attribute: .Bottom, multiplier: 1.0, constant: 0).active = true

2 个答案:

答案 0 :(得分:7)

我会回应what vacawama said in his excellent answer关于使用布局锚点。它可能与您使用本机API一样清晰和优雅,但请注意它需要iOS 9及更高版本。

出于代码组织的目的,我建议您不要寻找更严格的代码,而是将代码组织成方法和/或扩展,例如:

extension UIView {

    func constraintsAligningAllEdges(toView view2: UIView) -> [NSLayoutConstraint] {

        return [ topAnchor.constraintEqualToAnchor(view2.topAnchor),
                 bottomAnchor.constraintEqualToAnchor(view2.bottomAnchor),
                 leadingAnchor.constraintEqualToAnchor(view2.leadingAnchor),
                 trailingAnchor.constraintEqualToAnchor(view2.trailingAnchor) ]
    }
}

使用它看起来像这样:

NSLayoutConstraint.activateConstraints(greenView.constraintsAligningAllEdges(toView: redView))

...或者可能使它成为NSLayoutConstraint的类函数扩展。

关于 Visual Format Language 的主题,vacawama也提出了一个非常有趣的布局选项。这是实现同一目标的另一种可能方式:

let views = ["greenView" : greenView, "redView" : redView]

NSLayoutConstraint.activateConstraints(
    NSLayoutConstraint.constraintsWithVisualFormat("H:[greenView]-(0@1)-[redView]", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: views) +
    NSLayoutConstraint.constraintsWithVisualFormat("V:[greenView]-(0@1)-[redView]", options: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views)
)

我在这里所做的不是引入额外的视图,而是引入了两个无关的限制,一个在绿色底部和两个之间。红色顶部,另一个绿色尾随&最高领导。它们都具有1的最低优先级,因此您通常会有其他约束来决定任一视图的大小/位置,因此它们不会造成任何伤害。

这有点优雅吗?我不知道,但我个人认为布局锚对我来说更有意义,而像SnapKit这样的第三方框架也是不错的选择。

答案 1 :(得分:3)

可视格式语言不能用于所有可能的情况。我认为将这两种观点相互对齐就是这种情况。

我建议您使用布局锚点,如下所示:

override func viewDidLoad() {
    super.viewDidLoad()

    let redView = UIView()
    redView.backgroundColor = .redColor()
    redView.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(redView)

    let greenView = UIView()
    greenView.backgroundColor = .greenColor()
    greenView.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(greenView)

    let redHoriz = NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[redView]-20-|", options: [], metrics: nil, views: ["redView": redView])
    NSLayoutConstraint.activateConstraints(redHoriz)

    let redVert = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[redView]-50-|", options: [], metrics: nil, views: ["redView": redView])
    NSLayoutConstraint.activateConstraints(redVert)

    // Set greenView to occupy same space as the redView
    greenView.leftAnchor.constraintEqualToAnchor(redView.leftAnchor).active = true
    greenView.rightAnchor.constraintEqualToAnchor(redView.rightAnchor).active = true
    greenView.topAnchor.constraintEqualToAnchor(redView.topAnchor).active = true
    greenView.bottomAnchor.constraintEqualToAnchor(redView.bottomAnchor).active = true
}

可视格式语言允许您对齐视图的部分。例如,您可以通过将[.AlignAllTop, .AlignAllBottom]作为options的{​​{1}}参数传递来对齐两个视图的底部顶部。但是,您只能对齐与可视格式方向垂直的值。因此,如果要指定水平布局,则可以对齐视图的 tops bottom 。如果要指定垂直布局,则可以对齐 lefts 权限

您可以通过引入两个其他视图来对齐两个视图。在下面的示例中,蓝色视图选取红色视图的顶部底部对齐方式,黄色视图选取左侧右侧红色视图的对齐方式。然后绿色视图与蓝色视图的 top bottom 以及 left right 对齐黄色视图,因此它与红色视图对齐。

最后,隐藏蓝色和黄色视图会让您获得所需的设置。

VFL example

constraintsWithFormat

所以你可以用VFL来做,但它并不优雅。我建议你坚持使用锚点。