自动旋转时自动布局约束更新
Posted
技术标签:
【中文标题】自动旋转时自动布局约束更新【英文标题】:Autolayout constraints update on autorotation 【发布时间】:2019-10-10 14:42:53 【问题描述】:我对纵向和横向模式有不同的自动布局约束。我在旋转时激活和停用它们,但对于已停用的约束,仍然会出现无法满足的约束错误。这是我的工作:
//Initialization
slider.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(slider)
let landscapeConstraintTrailing = slider.trailingAnchor.constraint(equalTo: topPanel.trailingAnchor, constant: 0)
let landscapeConstraintTop = slider.topAnchor.constraint(equalTo: topPanel.bottomAnchor, constant: 5)
let landscapeConstraintBottom = slider.bottomAnchor.constraint(equalTo: bottomPanel.topAnchor, constant: -5)
let landscapeConstraintWidth = slider.widthAnchor.constraint(equalToConstant: 140)
self.sliderLandscapeConstraints = [landscapeConstraintTrailing,
landscapeConstraintTop,
landscapeConstraintBottom,
landscapeConstraintWidth]
for constraint in self.sliderLandscapeConstraints!
constraint.isActive = false
let portraitConstraintTrailing = slider.trailingAnchor.constraint(equalTo: bottomPanel.trailingAnchor, constant: -10)
let portraitConstraintBottom = slider.bottomAnchor.constraint(equalTo: bottomPanel.topAnchor, constant: -10)
let portraitConstraintLeading = slider.leadingAnchor.constraint(equalTo: bottomPanel.leadingAnchor, constant: 10)
let portraitconstraintHeight = slider.heightAnchor.constraint(equalToConstant: 140)
self.sliderPortraitConstraints = [portraitConstraintTrailing,
portraitConstraintBottom,
portraitConstraintLeading,
portraitconstraintHeight
]
for constraint in self.sliderPortraitConstraints!
constraint.isActive = false
现在在自动旋转,我这样做:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
let orientation = UIApplication.shared.statusBarOrientation
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: [unowned self] (_) in
let orient = UIApplication.shared.statusBarOrientation
layoutSlider(orient)
, completion: [unowned self] (UIViewControllerTransitionCoordinatorContext) -> Void in
let orient = UIApplication.shared.statusBarOrientation
layoutSlider(orient)
)
private func layoutSlider(_ orient:UIInterfaceOrient)
if orient.isLandscape
for constraint in self.sliderLandscapeConstraints!
constraint.isActive = true
for constraint in self.sliderPortraitConstraints!
constraint.isActive = false
else
for constraint in self.sliderLandscapeConstraints!
constraint.isActive = false
for constraint in self.sliderPortraitConstraints!
constraint.isActive = true
这是我在自动旋转时遇到的错误:
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2019-10-10 20:12:22.371021+0530 MyApp[1844:173193] [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:0x2810051d0 UIView:0x103a1d130.leading == UILayoutGuide:0x280a28b60'UIViewSafeAreaLayoutGuide'.leading + 5 (active)>",
"<NSLayoutConstraint:0x2810014f0 UIView:0x103a1d130.trailing == UILayoutGuide:0x280a28b60'UIViewSafeAreaLayoutGuide'.trailing + 5 (active)>",
"<NSLayoutConstraint:0x28101e490 MyApp.slider:0x103b2deb0.trailing == UIView:0x103a1d130.trailing - 10 (active)>",
"<NSLayoutConstraint:0x28101e3a0 MyApp.slider:0x103b2deb0.leading == UIView:0x103a1d130.leading + 10 (active)>",
"<NSLayoutConstraint:0x28101e350 MyApp.slider:0x103b2deb0.width == 140 (active)>",
"<NSLayoutConstraint:0x281060690 'UIView-Encapsulated-Layout-Width' UIView:0x103b23410.width == 812 (active)>",
"<NSLayoutConstraint:0x281001900 'UIViewSafeAreaLayoutGuide-left' H:|-(44)-[UILayoutGuide:0x280a28b60'UIViewSafeAreaLayoutGuide'](LTR) (active, names: '|':UIView:0x103b23410 )>",
"<NSLayoutConstraint:0x2810019a0 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x280a28b60'UIViewSafeAreaLayoutGuide']-(44)-|(LTR) (active, names: '|':UIView:0x103b23410 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x28101e350 MyApp.slider:0x103b2deb0.width == 140 (active)>
【问题讨论】:
【参考方案1】:顺序很重要,您应该先停用然后再激活,以免造成冲突
private func layoutSlider(_ orient:UIInterfaceOrient)
if orient.isLandscape
// false should be first
for constraint in self.sliderPortraitConstraints!
constraint.isActive = false
for constraint in self.sliderLandscapeConstraints!
constraint.isActive = true
else
// false should be first
for constraint in self.sliderLandscapeConstraints!
constraint.isActive = false
for constraint in self.sliderPortraitConstraints!
constraint.isActive = true
【讨论】:
糟糕,就是这样。以上是关于自动旋转时自动布局约束更新的主要内容,如果未能解决你的问题,请参考以下文章