我一直在尝试以纯代码(不使用故事板)构建自适应布局并开始运行。我使用布局锚来设置约束并利用 traitCollectionDidChange 方法在各种约束集和其他界面更改之间进行更改。我使用 switch 语句来调用具有相应约束集的相应方法。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
switch (traitCollection.horizontalSizeClass, traitCollection.verticalSizeClass) {
case (.regular, .regular):
setupRegularRegular()
case (.compact, .compact):
setupCompactCompact()
case (.regular, .compact):
setupRegularCompact()
case (.compact, .regular):
setupCompactRegular()
default: break
}
}
为了测试,我只更改了一个约束,即 centerYAnchor.constraint。在纵向中,常数为 -150,在横向中我希望将其更改为 50。对于 iPad,我将常数设置为 0。
bigLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -150).isActive = true
在 iPhone 和 iPad 之间切换时效果很好。但是,如果您开始将 iPhone 从纵向旋转到横向,布局系统将失败,并显示:
[LayoutConstraints] 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.
(
"<NSLayoutConstraint:0x600000097890 UILabel:0x7fac02c08aa0'Main Label'.centerY == UIView:0x7fac02e0a950.centerY - 150 (active)>",
"<NSLayoutConstraint:0x604000097840 UILabel:0x7fac02c08aa0'Main Label'.centerY == UIView:0x7fac02e0a950.centerY + 50 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x604000097840 UILabel:0x7fac02c08aa0'Main Label'.centerY == UIView:0x7fac02e0a950.centerY + 50 (active)>
我尝试覆盖各种方法并将约束的 isActive 属性设置为 false,然后再设置为 true,但这并没有帮助。我在网上搜索了几天。至今没有解决办法。所以我的问题是,在旋转设备时,您如何以正确的方式在尺寸等级之间切换?是否有必要覆盖任何其他方法或其他东西?纯代码中的自适应布局有更好的解决方案吗?当涉及到代码中的自适应布局/大小类/布局锚点和约束(不使用情节提要)时,是否有任何最佳实践?感谢帮助!
PS设置约束的方法是:
func setupCompactRegular() {
bigLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -150).isActive = true
}
func setupRegularCompact() {
bigLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 50).isActive = true
}