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

问题描述:

下面我已经包含了一些代码供您检出。我正在尝试自定义UIView并为其添加另一个自定义子视图。这个子视图应该被限制在父视图中,它基本上只是在相同的尺寸上放置在顶层,父层只是用作包装。以编程方式为UIView的子视图设置自动布局约束条件

我已经尝试过使用NSLayoutConstraint,迄今为止失败了。该视图从未真正显示出来。我有一个左侧,右侧,底部和顶部的约束,应该与父视图对齐。

我的第一个问题是,有人请使用下面的方法解释和纠正我的逻辑。我想要的项目参数是您想为(customViewChild)设置约束的实际视图。该属性是说我希望我的customViewChild的左边缘用于此约束。 relatedBy似乎是非常直接的,虽然我可能是错的,然后最后toItem指向自我这是我的也有.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]); 
    } 

} 
+0

摆脱customViewChild.addConstraint的'。 ..'。将'isActive'设置为true会将它们添加到正确的视图中。 – vacawama

+0

您是从故事板或笔尖文件创建'CustomViewParent'的实例吗?如果不是那么'init(coder:)'可能没有被调用。使用断点或日志来确认。另外,我建议你使用.leading和.trailing,而不是.left和.right。 – Paulw11

三件事:

  1. 你并不需要使用addConstraint。为约束设置isActivetrue
  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 
} 

你可能觉得这有点容易,更具可读性...

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 
    } 

}