以编程方式为UIView的子视图设置自动布局约束

4

以下是一些代码供您查看。我正在尝试获取一个自定义的UIView并添加另一个自定义子视图。这个子视图应该被约束到父视图上,以便它基本上只是覆盖在上面,并具有相同的尺寸,而父视图则充当包装器。

我已经尝试使用NSLayoutConstraint,但迄今为止都失败了。这个视图实际上从未显示出来。我有一个左、右、下和上的约束,应该与父视图对齐。

首先,我想请有人解释并纠正我的逻辑,使用以下方法。我发现item参数是您要设置约束的实际视图(customViewChild)。属性是指我希望使用我的customViewChild的左边缘进行此约束。relatedBy似乎很简单,虽然我可能错了,最后toItem指向self,这是我的CustomViewParent,它还具有一个.left属性,以表示我希望我的子级和父级的左边缘对齐。这个逻辑有问题吗或者我做错了什么?

NSLayoutConstraint(item: customViewChild!, 
            attribute: .left, 
            relatedBy: .equal,
            toItem: self,
            attribute: .left, 
            multiplier: 1.0, 
            constant: 0.0)

我知道下面的例子可以很容易地使用IB完成,但是我正在尝试理解NSLayoutConstraint,所以请提供关于它的答案。最后,如果有人能够纠正这段代码,让我有一个可用的示例,那就太棒了。

class CustomViewParent: UIView {

    var customViewChild: UIView?

    override init(frame: CGRect) {
        super.init(frame: frame)

        setConstraints()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setConstraints()
    }

    func setConstraints() {
        customViewChild = UIView()

        addSubview(customViewChild!)
        customViewChild?.translatesAutoresizingMaskIntoConstraints = false

        let leftConstraint = NSLayoutConstraint(item: customViewChild!, 
            attribute: .left, 
            relatedBy: .equal,
            toItem: self,
            attribute: .left, 
            multiplier: 1.0, 
            constant: 0.0).isActive = true

        let rightConstraint = NSLayoutConstraint(item: customViewChild!, 
            attribute: .right, 
            relatedBy: .equal,
            toItem: self,
            attribute: .right, 
            multiplier: 1.0, 
            constant: 0.0).isActive = true

        let topConstraint = NSLayoutConstraint(item: customViewChild!, 
            attribute: .top, 
            relatedBy: .equal,
            toItem: self,
            attribute: .top,
            multiplier: 1.0, 
            constant: 0.0).isActive = true

        let bottomConstraint = NSLayoutConstraint(item: customViewChild!, 
            attribute: .bottom, 
            relatedBy: .equal,
            toItem: self,
            attribute: .bottom, 
            multiplier: 1.0, 
            constant: 0.0).isActive = true

        customViewChild.addConstraint([leftConstraint, rightConstraint, topConstraint, bottomConstraint]);
    }

}

1
摆脱 customViewChild.addConstraint...。将 isActive 设置为 true 将它们添加到正确的视图中。 - vacawama
你是从Storyboard或Nib文件中创建了CustomViewParent的实例吗?如果不是,那么init(coder:)可能没有被调用。使用断点或日志进行确认。此外,我建议你使用.leading.trailing而不是.left.right - Paulw11
2个回答

8
您可能会发现这样更加容易理解和阅读...
func setConstraints() {

    if customViewChild == nil {
        customViewChild = UIView()

        addSubview(customViewChild!)
        customViewChild?.translatesAutoresizingMaskIntoConstraints = false

        customViewChild?.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        customViewChild?.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        customViewChild?.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        customViewChild?.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    }

}

4

三件事情:

  1. 你不需要使用 addConstraint,只需为约束设置 isActive 属性值为 true
  2. isActive 属性值设置为 true 并将其赋值给常量没有意义。设置 isActive 属性并不会返回 NSLayoutConstraint 对象,它只会返回 ()
  3. 你应该使用 .leading.trailing 替代 .left.right

经过上述更改,以下代码应该可以正常工作:

func setConstraints() {
    customViewChild = UIView()

    addSubview(customViewChild!)
    customViewChild?.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint(item: customViewChild!, 
        attribute: .leading, 
        relatedBy: .equal,
        toItem: self,
        attribute: .leading, 
        multiplier: 1.0, 
        constant: 0.0).isActive = true

    NSLayoutConstraint(item: customViewChild!, 
        attribute: .trailing, 
        relatedBy: .equal,
        toItem: self,
        attribute: .trailing, 
        multiplier: 1.0, 
        constant: 0.0).isActive = true

    NSLayoutConstraint(item: customViewChild!, 
        attribute: .top, 
        relatedBy: .equal,
        toItem: self,
        attribute: .top,
        multiplier: 1.0, 
        constant: 0.0).isActive = true

    NSLayoutConstraint(item: customViewChild!, 
        attribute: .bottom, 
        relatedBy: .equal,
        toItem: self,
        attribute: .bottom, 
        multiplier: 1.0, 
        constant: 0.0).isActive = true
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接