ScrollView 自动布局约束打破设备旋转
Posted
技术标签:
【中文标题】ScrollView 自动布局约束打破设备旋转【英文标题】:UIScrolView auto layout contraints breaking on device rotation 【发布时间】:2014-09-03 12:24:01 【问题描述】:在UIScrollView
及其子视图上设置自动布局约束时,我遇到了一个相当烦人的问题。当设备方向改变时,它会通过以下警告打破约束:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this: (1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7a1b1830 V:[UIView:0x7a1b0520(768)]>",
"<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>",
"<NSLayoutConstraint:0x7a17aa70 V:|-(0)-[UIView:0x7a1b0520] (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a1c49c0 V:[UIView:0x7a1b0520]-(0)-| (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a172620 V:[UIView:0x7a1bcf50]-(0)-| (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a172650 V:|-(0)-[UIView:0x7a1bcf50] (Names: '|':UIScrollView:0x7a176520 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>
我在故事板中设置了一个滚动视图,它包含两个容器作为子视图。滚动视图本身固定在超级视图的所有四个侧面(编辑器/引脚/前导-、尾随-、顶部-、底部-空间到超级视图)。这两个容器的边缘通过 Auto-Layout 约束固定到滚动视图,但两者的宽度和高度在情节提要上设置为固定,请参阅 att。图片:
两个容器的宽度和高度通过代码更新,最初是在viewDidLoad()
中,每当设备方向改变时,在didRotateFromInterfaceOrientation()
中:
_primaryWidth.constant = view.bounds.size.width
_primaryHeight.constant = view.bounds.size.height
_secondaryWidth.constant = _primaryWidth.constant - 200
_secondaryHeight.constant = _primaryHeight.constant
这是出现上述警告并且约束中断并且布局过度的时候。有人能告诉我为什么会发生这种情况以及如何解决吗?
(注意负 200。这是因为正确的容器应该有更小的宽度。但这不会影响问题。即使没有这个,约束也会中断。)
【问题讨论】:
不需要像自动布局那样改变高度和宽度。此外,警告是当您应用过多的自动布局时,您需要更好地阅读自动布局并尝试使用简单的示例来理解它。 如果我在设备旋转后不更新两个容器的宽度/高度,它们将不会将它们的大小更新到屏幕 w/h,这会导致它们垂直滚动并具有错误的大小。 所以自动布局是为了控制调整你的布局。您应该以编程方式而不是 IB 进行自动布局。 @walle84 我对这个逻辑的问题是,如果像这样简单的事情不能用 IB 完全完成,那么 IB 有什么用?!幸运的是,我现在通过 IB 让它工作了。 以编程方式以防万一我们有复杂的视图,那么在这种情况下,IB 就没那么有用了。同样,就像我们有时以编程方式而不是从 IB 获取 uibutton 的原因一样。所以一切都取决于流动。也很好,它可以正常工作,并且 DBD 提供的答案很好!!!! 【参考方案1】:您有将滚动视图的边缘固定到屏幕边缘的约束,这适用于纵向和横向。您还有一个约束,将您的一个视图的高度设置为 1024。
在纵向中一切正常,但是当您旋转到横向时,您不能将高度为 1024 的东西固定在顶部和底部的屏幕边缘,因为屏幕的高度仅为 768。一个必须去,你可以看到哪个得到斧头。
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>
删除高度限制,你会没事的。为什么你仍然需要它们?无论您给定的大小如何,您都希望视图固定到屏幕/超级视图的边缘。非任意值还允许您将相同的代码/布局携带到其他设备或作为子视图而无需更改布局。
【讨论】:
感谢@DBD 的提示,但是我在情节提要中没有设置任何限制,设置为 1024 高度。容器视图约束的高度唯一更新的地方是在上面的代码中的 didRotateFromInterfaceOrientation() 中。这是必要的,因为否则容器视图的高度与屏幕高度不同。 哇!自动布局到底有多令人困惑?!以为我几乎想通了。在滚动视图中添加了两个容器的宽度约束,然后应用“添加缺少的约束”这几乎是正确的,即使在旋转到横向时也是如此。但是随后旋转回 Portrait 并且第二个容器视图的宽度和高度没有更新。在这个问题上浪费的时间:3.45 小时。 想通了!奇怪的是,从另一个相关类中的错误视图中获取的宽度导致高度混乱。以上是关于ScrollView 自动布局约束打破设备旋转的主要内容,如果未能解决你的问题,请参考以下文章