【发布时间】:2021-12-02 16:49:03
【问题描述】:
我在 Xcode 13 中使用以下布局作为自定义弹出窗口UIView(白色背景是透明的):
当屏幕方向更改为横向模式时,顶部和底部的约束仍然是 100pts。正因为如此,中间部分(黄色,UIView 和 UIStackView 和 UITableView,...内部)非常小,并且控制台中会出现关于顶部(红色)和底部(蓝色)栏的警告:
无法同时满足约束。
我知道这个警告意味着什么。为了修复它,我创建了以下函数...
private let constraintPortrait:CGFloat = 100
private let constraintLandscape:CGFloat = 10
private func fixConstraints() {
if (UIDevice.current.orientation == .landscapeLeft || UIDevice.current.orientation == .landscapeRight) && UIDevice.current.userInterfaceIdiom == .phone {
topConstraint.constant = constraintLandscape
bottomConstraint.constant = constraintLandscape
} else {
topConstraint.constant = constraintPortrait
bottomConstraint.constant = constraintPortrait
}
}
... 并在 viewDidLoad 和 viewDidLayoutSubviews 中调用它。这很好用,但时不时会弹出警告,所以我将打印添加到viewDidLoad,... 并注意到警告实际上是在调用约束修复之前打印的。我将 viewDidLayoutSubviews 重命名为 viewWillLayoutSubviews(UIViewController 生命周期 here)和 Abracadabra!,警告消失了。
人们通常推荐使用viewDidLayoutSubviews,当你想在设备旋转后做一些事情时,但几乎没有提到viewWillLayoutSubviews,在寻找原因时我找到了this answer,说不要使用后者来更改约束,因为它可能会导致另一个自动布局传递。
问题:
我应该改用什么来防止冲突(不更改纵向模式的固定约束!)?有没有办法在界面生成器中自动更改顶部和底部约束,而不使用任何代码,并且仅在实际需要时(-> 始终将 100pts 保持在纵向模式,即使是长桌,但立即切换到 10pts空间不足时在横向模式下)?
【问题讨论】:
-
您确定错误发生的原因吗?使用您在问题中显示的约束,除非您在某处有固定的宽度/高度约束,否则我不会期望方向的变化会导致无法满足的约束? (或类似的东西)。您可以将自动布局错误发布到问题中吗?或者,这个工具非常适合可视化错误wtfautolayout.com
-
嗯...又看了一遍...您是否试图将“弹出”视图置于父视图中间?如果是这样,那么执行此操作的限制较少。
-
@Fogmeister 我再次检查了警告,肯定首先提到了红色和蓝色的 UIView (50pts)。之后它抱怨 100pts,然后有一些关于 320pts 的固定高度的东西,我不确定它来自哪里(必须再次检查)。我不能改变红色或蓝色视图的高度,因为我希望整个东西看起来像一个普通的
UIAlertController,所以下一个最好的事情是改变 100pts 约束(这有效但可能不是正确的方法它)。 -
是的,我想将弹出窗口居中放在父视图的中间,但也不希望它变得太大,这就是我使用约束的原因(它适用于小型和大设备)而不是固定高度,对于大型设备来说可能太小而对于小型设备来说太大。
-
我认为在这里以相反的方式处理这个问题并在弹出视图上设置最大高度/宽度可能是有意义的。所以它的大小是在内部定义的,而不是在外部定义的。然后让它在父视图中居中。如果您想为父视图边缘设置最小间距(您的 100 点约束),那么仍然拥有它们,但将它们设置为
>= 100而不是==100。这意味着您根本不必针对不同的方向更改它们。
标签: ios swift autolayout nslayoutconstraint