ios - 旋转设备时更改约束
问题描述
我UIView
在 Xcode 13 中使用以下布局作为自定义弹出窗口(白色背景是透明的):
当屏幕方向更改为横向模式时,顶部和底部的约束仍然是 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
的生命周期)和 Abracadabra!,警告消失了。
人们通常建议viewDidLayoutSubviews
在设备旋转后想要做一些事情时使用,但几乎没有提及viewWillLayoutSubviews
,并且在寻找原因时我找到了这个答案,说不要使用后者来更改约束,因为它可能会导致另一个自动布局通过。
问题:
我应该使用什么来防止冲突(不更改纵向模式的固定约束!)?有没有办法在界面生成器中自动更改顶部和底部约束,而不使用任何代码,并且仅在实际需要时(-> 始终将 100pts 保持在纵向模式,即使是长桌,但立即切换到 10pts在没有足够空间时处于横向模式)?
解决方案
viewWillLayoutSubviews
是正确的。您在此处执行的任何布局更改,包括约束更改,都将自动与旋转动画相协调。
但是你怎么知道这个调用viewWillLayoutSubviews
是由于轮换引起的?实现这个方法:
https://developer.apple.com/documentation/uikit/uicontentcontainer/1621466-viewwilltransition
或者,在 iPhone 上,这种方法:
https://developer.apple.com/documentation/uikit/uicontentcontainer/1621511-willtransition
我喜欢前者,因为它适用于 iPad 和 iPhone。这些在之前被调用viewWillLayoutSubviews
,因此您可以设置一个实例属性来向自己发出信号,表明尺寸正在正式更改。您可以通过将边界大小高度与边界大小宽度进行比较来确定发生了什么,并相应地更改约束。
推荐阅读
- php - 正则表达式 - 转义方括号和边界
- java - 如何告诉 JPA 管理依赖实体?
- spring-security - 使用 OAuth2 保护服务,JWT 令牌不起作用 Spring Cloud
- hyperledger-fabric - 当我尝试批准链码时,Hyperledger Fabric Orderer 收到权限被拒绝
- css - 如何在 Qt 中使 MainWindow 的背景图像不覆盖子窗口小部件的
- windows - findstr:提供比预期更多的匹配项
- javascript - Webpack 解析别名并在该别名下编译文件
- string - 如何将三个句子的列表制作成一个字符串?
- python - 加快 Cython 中的 numpy 调用
- c# - 在 Windows 服务上使用单例上下文会更好吗?