当尺寸改变时,如何更新自动布局约束?

9
我在一个包含UIView的视图底部布置了几个UIView。我希望这些视图始终具有相等的宽度,并且始终可以共同填充包含视图的宽度(就像底部的表情符号键盘按钮)。我的方法是将其中一个视图设置为等宽,然后只需更新该视图的宽度约束为superviewWidth / numberOfViews,所有其他视图都会更新为相同的值。
我想知道更改约束常量的代码应放在何处。它需要在键盘第一次出现在屏幕上之前进行设置,并在旋转设备时进行更新。
我尝试了一个解决方案,即将其放置在updateViewConstraints中,并通过containerView.frame.size.width计算宽度。但是,此方法在加载时被调用两次,第一次正确计算值,但由于某种原因,第二次containerView的宽度为0.0。另一个问题是,在旋转时,containerView的宽度不是旋转后的值,而是旋转前的当前值。但我不想等到旋转完成后再更新约束,因为按钮将先是原始大小,然后才会更改,这会让用户感到困惑。
我的问题是:放置此代码的最合适位置是什么?是否有更好的方法来计算宽度?我可以保证其宽度始终与屏幕宽度完全相同。我正在使用Xcode 6中的Size Classes,因此willRotateToInterfaceOrientation和类似方法已被弃用。
2个回答

9

当实现了UITraitEnvironment协议的所有类的特征集合发生更改时(例如旋转),将调用traitCollectionDidChange方法。这是在使用新的Size Classes时手动更新约束的适当位置。您还可以使用willTransitionToTraitCollection方法动画过渡。

基本示例:

class ViewController: UIViewController {

  var constraints = [NSLayoutConstraint]()

  func updateConstraintsWithTraitCollection(traitCollection: UITraitCollection) {
    // Remove old constraints
    view.removeConstraints(constraints)

    // Create new constraints
  }

  override func willTransitionToTraitCollection(newCollection: UITraitCollection!,
    withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator!) {

      super.willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator)

      coordinator.animateAlongsideTransition({ (context: UIViewControllerTransitionCoordinatorContext!) in
        self.updateConstraintsWithTraitCollection(newCollection)
        self.view.setNeedsLayout()
      }, completion: nil)

  }

  override func traitCollectionDidChange(previousTraitCollection: UITraitCollection!) {
    updateConstraintsWithTraitCollection(traitCollection)
  }
}

除此之外,我想推荐一款名为Cartography的优秀库,它可以帮助使自动布局更易读且更有趣。请参考https://github.com/robb/Cartography

谢谢,虽然我已经实现了 drewag 的解决方案,但我相信这会很有用。 - Jordan H
你真是救星啊。我终于找到并删除了那些通过UIView.constraints()在ViewDidLoad()和拦截屏幕方向willRotateToInterfaceOrientation()时无法找到的“幽灵”约束。 - clearlight

3

没有必要手动更新宽度:

  1. 将所有等宽视图放置在视图中,彼此之间没有间隔
  2. 为它们添加相等的宽度约束
  3. 添加零宽度的约束以便于两侧和彼此之间的间距
  4. 如果宽度无法平均分配,请降低一个或多个等宽约束的优先级。

然后自动布局会为您处理一切。


谢谢您提出更好的解决方案!现在运行得非常好。 - Jordan H

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