【问题标题】:Programatically setting auto layout constraints for a UIView's subviews以编程方式为 UIView 子视图设置自动布局约束
【发布时间】:2017-04-04 20:22:19
【问题描述】:

下面我提供了一些代码供您结帐。我正在尝试采用自定义 UIView 并向其添加另一个自定义子视图。这个子视图应该以这样的方式被限制在父视图上,它基本上只是以相同的尺寸放置在顶部,而父视图只是充当包装器。

我已经尝试使用NSLayoutConstraint 并且到目前为止失败得很惨。该视图从未真正出现过。我有一个左、右、下和上约束,应该与父视图对齐。

我的第一个问题是,在使用以下方法时,请有人解释或纠正我的逻辑。我想出的项目参数是您要为其设置约束的实际视图 (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]);
    }

}

【问题讨论】:

  • 摆脱customViewChild.addConstraint...。将 isActive 设置为 true 会将它们添加到正确的视图中。
  • 您是从情节提要或 nib 文件创建CustomViewParent 的实例吗?如果没有,那么init(coder:) 可能不会被调用。使用断点或日志来确认。另外,我建议您使用 .leading 和 .trailing 而不是 .left 和 .right。

标签: ios swift nslayoutconstraint ios-autolayout


【解决方案1】:

您可能会发现这更容易,更易读...

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
    }

}

【讨论】:

    【解决方案2】:

    三件事:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-26
      • 2018-02-04
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多