设置相对于设备尺寸的自动布局约束

Set Autolayout Constraints Relative to Device Size

我掉进了依赖Autolayout的陷阱。我目前有一个带有大量 UIView 的 ViewController,我意识到它们在较小的设备(iPhone 4s 和 5)上失真。

是否可以在 Autolayout 中设置相对于设备大小的约束。

例如,我有一个 UIView 与其他几个 UIViews 对齐的边缘。我想将那个 UIView 在自动布局中的高度更改为设备高度的一半。

是的。有一种方法可以通过屏幕尺寸进行限制。

他们被称为size classes

在 Interface Builder 中查看屏幕底部的栏,上面写着 wAny hAny,这些是下拉菜单。 Select 设备的高度和宽度的组合以及您要将其约束到的方向,当您在该模式下创建约束时,它们将特定于该 size/orientation。您还可以在 Interface Builder 的检查器、约束编辑器窗格中添加和修改特定于大小的约束。

如果您需要调整一些您无法通过大小分类方便地完成的极端情况,您可以为约束创建一个 IBOutlet 并在您的代码中引用它,并在视图出现时修改它和变化,类似于下面的例子。这比尝试以编程方式从头开始生成约束要容易和安全得多。

注意:当通过 IB 出口修改 NSLayout 约束时,您只能调整 constant 字段,而不是 multiplier,因为 multiplier 在运行时是只读的。因此,无论您使用什么比例因子(如果有的话)都必须乘以您用于常量的任何最终值。

@IBOutlet var tableYTopConstraint : NSLayoutConstraint!

override func viewWillAppear(animated: Bool) {
     adjustViewLayout(UIScreen.mainScreen().bounds.size)
}

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        adjustViewLayout(size)
}

func adjustViewLayout(size: CGSize) {
    switch(size.width, size.height) {
    case (320, 480):                        // iPhone 4S in portrait
        tableYTopConstraint.constant = 0
    case (480, 320):                        // iPhone 4S in landscape
        tableYTopConstraint.constant = 0
    case (320, 568):                        // iPhone 5/5S in portrait
        tableYTopConstraint.constant = 0
    case (568, 320):                        // iPhone 5/5S in landscape
        tableYTopConstraint.constant = 0
    case (375, 667):                        // iPhone 6 in portrait
        tableYTopConstraint.constant = 0
    case (667, 375):                        // iPhone 6 in landscape
        tableYTopConstraint.constant = 0
    case (414, 736):                        // iPhone 6 Plus in portrait
        tableYTopConstraint.constant = 0
    case (736, 414):                        // iphone 6 Plus in landscape
        tableYTopConstraint.constant = 0
    default:
        break
    }
    view.setNeedsLayout()

}