使用VFL在NSView中对齐NSView

时间:2015-04-11 12:09:40

标签: macos cocoa swift autolayout visual-format-language

我有一个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)
}

布局可以是LeftRightCenterX (内部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")

    }
}

对齐RightCenter工作正常,但对齐left无效。

另外,由于垂直定心对于所有情况都是可以从开关盒中取出的吗?

1 个答案:

答案 0 :(得分:2)

几个问题:

  1. 您通常不会在VFL中明确列出超级视图。而是使用垂直线(|)字符。这样:

    H:[superview]-(<=1)-[innerView]
    

    并不意味着innerView的前沿在超级视图的前沿之后小于1点。这意味着innerView的前沿在超级视图的尾随边缘之后不到1点,这可能会使innerView超出其超级视图的边界,这将导致它削波。

  2. 如果这些是您添加影响innerView的唯一约束,则您的布局不明确。不等式允许任何可能的值,并且系统没有可靠的方法来挑选其中任何一个值。

  3. 你无法真正表达VFL的中心。您可以将对齐标记传递给constraintsWithVisualFormat(_:options:metrics:views:)(正如您所知),但是a)这不是视觉格式语言的一部分,而b)如果不创建一些虚假的话,你就不能这样做,另一个方向的不受欢迎的约束。也就是说,除非您还创建了一些虚假的水平约束,否则不能使用对齐标记来垂直居中。 (反之亦然。)那是因为对齐标志仅适用于VFL字符串中列出的视图,而VFL字符串总是暗示约束。

  4. 为什么坚持使用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)
    

    这将处理所有三种情况。