我有一个NSView的Subview(比如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
(内部TextView将始终垂直居中,只有水平对齐可以变化)
以下函数对目的进行约束
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")
}
}
对齐Right
和Center
工作正常,但对齐left
无效。
另外,由于垂直定心对于所有情况都是可以从开关盒中取出的吗?
答案 0 :(得分:2)
几个问题:
您通常不会在VFL中明确列出超级视图。而是使用垂直线(|
)字符。这样:
H:[superview]-(<=1)-[innerView]
并不意味着innerView
的前沿在超级视图的前沿之后小于1点。这意味着innerView
的前沿在超级视图的尾随边缘之后不到1点,这可能会使innerView
超出其超级视图的边界,这将导致它削波。
如果这些是您添加影响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)
这将处理所有三种情况。