我想使用"自动布局视觉格式"将两个视图放在同一位置。在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
答案 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 对齐黄色视图,因此它与红色视图对齐。
最后,隐藏蓝色和黄色视图会让您获得所需的设置。
constraintsWithFormat
所以你可以用VFL来做,但它并不优雅。我建议你坚持使用锚点。