Haa*_*nti 9 ios autolayout swift adaptive-layout
我想根据宽度是否大于高度来改变我的布局.但我不断收到布局警告.我在自适应布局上观看了两个WWDC视频,这些视频帮了很多但没有解决问题.我使用以下代码创建了一个简单版本的布局.这只是让人们可以重现我的问题.代码在iPhone 7 plus上运行.
import UIKit
class ViewController: UIViewController {
var view1: UIView!
var view2: UIView!
var constraints = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
view1 = UIView()
view1.translatesAutoresizingMaskIntoConstraints = false
view1.backgroundColor = UIColor.red
view2 = UIView()
view2.translatesAutoresizingMaskIntoConstraints = false
view2.backgroundColor = UIColor.green
view.addSubview(view1)
view.addSubview(view2)
layoutPortrait()
}
func layoutPortrait() {
let views = [
"a1": view1,
"a2": view2
]
constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[a1]|", options: [], metrics: nil, views: views)
constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[a2]|", options: [], metrics: nil, views: views)
constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[a1(450)][a2]|", options: [], metrics: nil, views: views)
NSLayoutConstraint.activate(constraints)
}
func layoutLandscape() {
let views = [
"a1": view1,
"a2": view2
]
constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[a1(a2)][a2(a1)]|", options: [], metrics: nil, views: views)
constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[a1]|", options: [], metrics: nil, views: views)
constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[a2]|", options: [], metrics: nil, views: views)
NSLayoutConstraint.activate(constraints)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
NSLayoutConstraint.deactivate(constraints)
constraints.removeAll()
if (size.width > size.height) {
layoutLandscape()
} else {
layoutPortrait()
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我旋转几次时,xcode会记录警告.我想我的布局切换到了早期,因为它仍然在变化,但我已经将肖像的高度设置为大或者其他东西.有人知道我做错了吗?
约束警告:(从景观回到肖像时发生)
[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:0x618000081900 V:|-(0)-[UIView:0x7ff68ee0ac40] (active, names: '|':UIView:0x7ff68ec03f50 )>",
"<NSLayoutConstraint:0x618000081d60 UIView:0x7ff68ee0ac40.height == 450 (active)>",
"<NSLayoutConstraint:0x618000083cf0 V:[UIView:0x7ff68ee0ac40]-(0)-[UIView:0x7ff68ee0ade0] (active)>",
"<NSLayoutConstraint:0x618000083d40 V:[UIView:0x7ff68ee0ade0]-(0)-| (active, names: '|':UIView:0x7ff68ec03f50 )>",
"<NSLayoutConstraint:0x600000085d70 'UIView-Encapsulated-Layout-Height' UIView:0x7ff68ec03f50.height == 414 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x618000081d60 UIView:0x7ff68ee0ac40.height == 450 (active)>
Run Code Online (Sandbox Code Playgroud)
你是对的,你太早做约束工作了。...<NSLayoutConstraint:0x600000085d70 'UIView-Encapsulated-Layout-Height' UIView:0x7ff68ec03f50.height == 414
是系统为视图控制器的横向视图高度创建的约束 - 为什么它是 414,恰好是 iPhone 5.5 (6/7 Plus) 横向高度。旋转尚未开始,垂直约束与 450 高度约束冲突,您会收到警告。
因此,您必须在旋转完成后添加约束。viewWillLayoutSubviews
是逻辑位置,因为当视图大小准备好但在屏幕上出现任何内容之前,它会被调用,并且可以保存系统本来会进行的布局传递。
但是,要消除警告,您仍然需要删除viewWillTransition(to size: with coordinator:)
. 系统在viewWillLayoutSubviews()
调用之前会进行新的自动布局计算,当从纵向变为横向时,您会收到相反的警告。
编辑:正如 @sulthan 在评论中指出的那样,由于其他事情可以触发布局,因此您还应该在添加约束之前始终删除约束。如果[constraints]
数组被清空则没有任何效果。由于停用后清空数组是关键步骤,因此应该在其自己的方法中进行,因此clearConstraints()
.
另外,请记住检查初始布局中的方向 - 您认为layoutPortrait()
这viewDidLoad()
当然不是问题。
新/更改方法:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// Should be inside layoutPortrait/Landscape methods, here to keep code sample short.
clearConstraints()
if (self.view.frame.size.width > self.view.frame.size.height) {
layoutLandscape()
} else {
layoutPortrait()
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
clearConstraints()
}
/// Ensure array is emptied when constraints are deactivated. Can be called repeatedly.
func clearConstraints() {
NSLayoutConstraint.deactivate(constraints)
constraints.removeAll()
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1531 次 |
最近记录: |