如何以编程方式添加约束,以便视图的高度恰好适合其最后一个子视图的底部?

时间:2015-12-04 20:21:03

标签: ios swift nslayoutconstraint

我有一个约束代码,它在容器视图(常规UIView)内从上到下垂直排列多个UILabel(4+)。我现在想要调整容器视图的大小,使其高度与我添加的最后一个标签的底部相匹配。

我试过这个:

let constraintPanelHeight = NSLayoutConstraint(item: cell.panelOptions, 
    attribute: .Height, relatedBy: .Equal, toItem: priorLabel!, 
    attribute: .Bottom, multiplier: 1, constant: 0)
cell.contentView.addConstraint(constraintPanelHeight)

但这会产生Invalid pairing of layout attributes错误,因为我正在匹配。一个视图的高度与子视图的.Bottom(我猜这就是原因)。

如何自动调整包含这样的视图?

2 个答案:

答案 0 :(得分:1)

我不知道你想要在那里实现什么。如果要将一个单元格固定到另一个单元格的底部,则必须使用属性.Top和高度的另一个约束。例如:您的视图中有10个标签,然后将您的高度设置为超级视图的十分之一:

let heightConstraint = NSLayoutConstraint(item: cell.panelOptions, attribute: .Height, relatedBy: .Equal, toItem: superview, attribute: .Height, multiplier: 0.1, constant: 0)

但是,由于iOS9还有UIStackView,这使得在视图中(垂直或水平)布置子视图非常容易。如果您想在高级视图中均匀地展开标签,请查看。

答案 1 :(得分:0)

如果您是固定数量的视图,最简单,最易读的方法是使用可视化布局格式和约束,如下所示: NSLayoutConstraint.constraints

WithVisualFormat("V:|[view1][view2][view3]|",
  options: NSLayoutFormatOptions.AlignAllCenterX,
  metrics: nil,
  views: ["view1": view1, "view2": view2,"view3": view3])

如果要添加变量数,原理是相同的,但是通过循环实现。你不应该设定任何东西的高度。让每个标签的intrinsicContentSize从内部大小容器。您可能需要将每个标签的contentCompressionResistance的优先级设置为1000,以确保标签不会被压扁。请记住,您还需要水平约束,但它们应该更容易解决。

这里是可变数量子视图的版本:

var prevView : UIView?
for view in views{
  container.addSubview(view)
  //
  // Add horizontal constraints for each view to fit the container
  // exclude for simplicity

  // Add vertical constraints
  if prevView == nil{
    container.addConstraint(NSLayoutConstraint(item: container,
      attribute: .Top,
      relatedBy: .Equal,
      toItem: view,
      attribute: .Top,
      multiplier: 1, constant: 0)
    )
  } else if view == views.last!{
    container.addConstraint(NSLayoutConstraint(item: container,
      attribute: .Bottom,
      relatedBy: .Equal,
      toItem: view,
      attribute: .Bottom,
      multiplier: 1,
      constant: 0))
  } else if let prev = prevView {
    container.addConstraint(NSLayoutConstraint(item: prev,
      attribute: .Bottom,
      relatedBy: .Equal,
      toItem: view,
      attribute: .Top,
      multiplier: 1,
      constant: 0))
  }
  prevView = view
}