首页 > 解决方案 > 界面构建器和以编程方式创建的视图之间的自动布局行为不一致

问题描述

我正在尝试以编程方式将子视图添加到垂直堆栈视图内的视图中。它应该尝试最大化其大小以填充其父视图,但仍保持其纵横比。我尝试通过添加具有默认优先级的纵横比约束来实现它。并添加低优先级的顶部、底部、前导、尾随和 centerX、centerY 约束。我在界面生成器中的原型工作得很好,但是当我将它翻译成代码时,边界处的间距丢失了。程序化版本中是否缺少某些内容?这是代码:

class ViewController: UIViewController {
    @IBOutlet var greenView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let testView = UIView()
        testView.backgroundColor = .red
        greenView.addSubview(testView)

        testView.translatesAutoresizingMaskIntoConstraints = false
        let aspectRatioConstraint = NSLayoutConstraint(item: testView,
                            attribute: .width,
                            relatedBy: .equal,
                            toItem: testView,
                            attribute: .height,
                            multiplier: 6.0 / 10.0,
                            constant: 0)

        let leadingConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .leading,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .leading,
                                             multiplier: 1,
                                             constant: 5)

        let trailingConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .trailing,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .trailing,
                                             multiplier: 1,
                                             constant: 5)

        let topConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .top,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .top,
                                             multiplier: 1,
                                             constant:5)

        let bottomConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .bottom,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .bottom,
                                             multiplier: 1,
                                             constant: 5)

        let centerXConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .centerX,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .centerX,
                                             multiplier: 1,
                                             constant: 0)

        let centerYConstraint = NSLayoutConstraint(item: testView,
                                             attribute: .centerY,
                                             relatedBy: .equal,
                                             toItem: greenView,
                                             attribute: .centerY,
                                             multiplier: 1,
                                             constant: 0)

        leadingConstraint.priority = .defaultLow
        trailingConstraint.priority = .defaultLow
        topConstraint.priority = .defaultLow
        bottomConstraint.priority = .defaultLow
        centerXConstraint.priority = .defaultLow
        centerYConstraint.priority = .defaultLow

        NSLayoutConstraint.activate([aspectRatioConstraint, leadingConstraint, trailingConstraint, topConstraint, bottomConstraint, centerXConstraint, centerYConstraint])

    }
}

以编程方式创建的损坏版本:缺少顶部和底部间距。

在此处输入图像描述

使用 Interface Builder 构建的预期外观:

使用界面生成器构建

这是IB中的设置:

这是IB中的设置

标签: swiftautolayoutios-autolayout

解决方案


我认为您想要的是greaterThanOrEqual用于顶部和前导,以及lessThanOrEqual用于右侧和底部。

试试这样:

class ThiniumViewController: UIViewController {
    @IBOutlet var greenView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let testView = UIView()
        testView.backgroundColor = .red

        greenView.addSubview(testView)

        testView.translatesAutoresizingMaskIntoConstraints = false

        let tvHeightConstraint = testView.heightAnchor.constraint(equalTo: testView.widthAnchor, multiplier: 10.0 / 6.0)
        tvHeightConstraint.priority = .defaultHigh

        let tvWidthConstraint = testView.widthAnchor.constraint(equalTo: greenView.widthAnchor, multiplier: 1.0)
        tvWidthConstraint.priority = .defaultHigh

        NSLayoutConstraint.activate([

            // center testView in greenView
            testView.centerXAnchor.constraint(equalTo: greenView.centerXAnchor),
            testView.centerYAnchor.constraint(equalTo: greenView.centerYAnchor),

            // constrain top and leading of redView to *at least* 5-points
            testView.topAnchor.constraint(greaterThanOrEqualTo: greenView.topAnchor, constant: 5.0),
            testView.leadingAnchor.constraint(greaterThanOrEqualTo: greenView.leadingAnchor, constant: 5.0),

            // constrain height of testView to width of testView at 10:6 ratio at Priority 750
            tvHeightConstraint,

            // constrain width of testView to width of greenView at Priority 750
            tvWidthConstraint,

            // constrain bottom and trailing of redView to *at least* 5-points
            testView.bottomAnchor.constraint(lessThanOrEqualTo: greenView.bottomAnchor, constant: -5.0),
            testView.trailingAnchor.constraint(lessThanOrEqualTo: greenView.trailingAnchor, constant: -5.0),

        ])

    }
}

作为旁注,您可能会发现更容易编写 - 并且更具可读性 - 构建您的约束,如我的示例代码所示。

结果:

在此处输入图像描述


推荐阅读