尺寸变化时,何处更新Autolayout约束?

时间:2014-07-12 18:41:10

标签: ios uiview rotation swift autolayout

我在包含UIView的底部放置了几个UIView。我希望这些视图始终具有相等的宽度,并始终拉伸以共同填充包含视图的宽度(如底部的表情符号键盘按钮)。我接近这个的方法是为其中一个视图设置相等的宽度,然后只需将该视图的宽度约束更新为superviewWidth / numberOfViews,这将导致所有其他视图更新为相同的值

我想知道更改约束常量的代码需要去哪里。需要在键盘首次出现在屏幕上之前进行设置,并在旋转设备时进行更新。

我首次尝试解决方案是将其放入updateViewConstraints并通过containerView.frame.size.width计算宽度。但是这个方法在加载时调用两次,第一次正确计算值,但第二次由于某种原因containerView的宽度为0.0。另一个问题是,在旋转时,containerView的宽度不是旋转后的值,它是旋转前的当前值。但我不想等到轮换完成后更新约束,因为按钮将是原始大小,然后更改将对用户产生不良影响。

我的问题是:放置此代码的最合适位置在哪里?有没有更好的方法来计算宽度?我可以保证它的宽度始终与屏幕宽度完全相同。我在Xcode 6中使用了大小类,因此不推荐使用willRotateToInterfaceOrientation和类似的方法。

2 个答案:

答案 0 :(得分:8)

在实现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

答案 1 :(得分:2)

没有理由手动更新宽度:

  1. 在视图中放置宽度相等的所有视图,彼此之间没有间距
  2. 为所有这些
  3. 添加相等的宽度约束
  4. 为边和两边之间的间距添加0宽度的约束
  5. 降低一个或多个相等宽度约束的优先级,以防宽度无法平均分配。
  6. 然后自动布局将为您处理所有事情。