【问题标题】:Where to update Autolayout constraints when size changes?大小更改时在哪里更新自动布局约束?
【发布时间】:2014-09-03 03:58:21
【问题描述】:

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

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

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

我的问题是:在哪里放置这段代码最合适?有没有更好的方法来计算宽度是多少?我可以保证它总是与屏幕宽度完全相同。而且我在 Xcode 6 中使用 Size Classes,因此不推荐使用 willRotateToInterfaceOrientation 和类似方法。

【问题讨论】:

    标签: ios uiview rotation swift autolayout


    【解决方案1】:

    在所有实现UITraitEnvironment 协议的类上,traitCollectionDidChange 方法将在特征集合发生变化时被调用,例如在轮换时。这是使用新尺寸类时手动更新约束的合适位置。您还可以使用 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

    【讨论】:

    • 谢谢,我相信即使我实现了drawag的解决方案,这也会派上用场。
    • 你是救生员。这是我终于看到并删除了我无法通过 ViewDidLoad() 的 UIView.constraints() 找到的“幽灵”约束的地方,并且在拦截屏幕方向时 willRotateToInterfaceOrientation()。
    【解决方案2】:

    没有理由手动更新宽度:

    1. 在视图中放置所有宽度相等的视图,彼此之间没有间距
    2. 为它们添加等宽约束
    3. 为边和彼此之间的间距添加宽度为 0 的约束
    4. 降低一个或多个等宽约束的优先级,以防无法等宽。

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

    【讨论】:

    • 感谢您提出更好的解决方案!工作得很好。
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多