1

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

布局可以是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")

    }
}

对齐Right并且Center工作正常,但对齐left不工作。

另外,由于垂直居中对所有情况都是通用的,因此可以将其从开关盒中取出吗?

4

1 回答 1

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)
    

    这将处理所有三种情况。

于 2015-04-11T14:49:24.637 回答