我有一个NSView的子视图(比如MainView),其中有NSTextField。
注:此代码基于此github.repo
MainView已指定初始化器如下
init(title : String, layout :NSLayoutAttribute) {
innerView = self.createTextField(title)//Text field with stringValue = title
mainView.addSubview(innerView)
createViewConstrants(innerView, layout: layout)
}
布局可以是
Left
、Right
或CenterX
。(内部文本视图将始终垂直居中,只有水平对齐方式可以改变)
以下函数为此目的进行约束
func createViewConstrants(view : NSView, layout :NSLayoutAttribute) {
let viewMap = ["innerView" : view, "superview" : mainView]
var constraints :[AnyObject]!
switch layout {
case .Left:
println("Left")
constraints = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[superview]-(<=1)-[innerView]",
options: NSLayoutFormatOptions.AlignAllCenterY,
metrics: nil,
views: viewMap)
mainView.addConstraints(constraints)
case .Right:
println("Right")
constraints = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[superview]-(<=1)-[innerView]-|",
options: NSLayoutFormatOptions.AlignAllCenterY,
metrics: nil,
views: viewMap)
mainView.addConstraints(constraints)
case .CenterX:
println("Center")
constraints = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[superview]-(<=1)-[innerView]",
options: NSLayoutFormatOptions.AlignAllCenterX,
metrics: nil,
views: viewMap)
mainView.addConstraints(constraints)
constraints = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[superview]-(<=1)-[innerView]",
options: NSLayoutFormatOptions.AlignAllCenterY,
metrics: nil,
views: viewMap)
mainView.addConstraints(constraints)
default:
fatalError("Invalid layout")
}
}
Align
Right
和Center
工作正常,但Alignleft
不工作。另外,由于垂直居中对所有的情况都是常见的,所以可以将其从开关箱中取出吗?
最佳答案
几个问题:
通常不会在VFL中显式列出superview。而是使用垂直线(|
)字符。这:
H:[superview]-(<=1)-[innerView]
并不意味着
innerView
的前缘在“superview”的前缘之后小于1点。这意味着innerView
的前缘在superview的后缘之后小于1点,这可能会使innerView
超出其superview的界限,从而导致其被剪裁。如果这些是您添加的唯一影响
innerView
的约束,那么您的布局是不明确的。一个不等式允许任何一个可能的值,并且系统没有可靠的方法来选择其中一个值。你不能在VFL中真正表达中心。您可以将对齐标志传递给
constraintsWithVisualFormat(_:options:metrics:views:)
(如您所知),但a)这实际上不是可视格式语言的一部分;b)如果不在另一个方向上创建一些虚假的、不需要的约束,则无法执行此操作。也就是说,除非同时创建一些虚假的水平约束,否则不能使用对齐标志垂直居中。(反之亦然)这是因为对齐标志只应用于VFL字符串中列出的视图,而VFL字符串总是包含约束。你为什么坚持使用VFL?如果使用
init(item:attribute:relatedBy:toItem:attribute:multiplier:constant:)
,则可以简单地传递方法接收的layout
参数。对于多个病例不需要switch
。你只要:var constraint = NSLayoutConstraint(item: innerView,
attribute: layout,
relatedBy: .Equal,
toItem: mainView,
attribute: layout
multiplier: 1,
constant: 0)
mainView.addConstraint(constraint)
constraint = NSLayoutConstraint(item: innerView,
attribute: .CenterY,
relatedBy: .Equal,
toItem: mainView,
attribute: .CenterY
multiplier: 1,
constant: 0)
mainView.addConstraint(constraint)
这将处理所有三个案件。