gpt4 book ai didi

ios - 当设备方向改变时,我应该禁用或删除布局约束吗?

转载 作者:搜寻专家 更新时间:2023-11-01 06:26:12 24 4
gpt4 key购买 nike

我正在以编程方式创建自适应布局。我的计划是有两组约束:portraitConstraintslandscapeConstraints。当设备改变方向时 (willTransition(to:)),我禁用以前的规则,并启用新规则。

portraitConstraints.append(photoView.topAnchor.constraint(equalTo: view.topAnchor))
....
portraitConstraints.append(canvas.trailingAnchor.constraint(equalTo: photoView.trailingAnchor))


landscapeConstraints.append(photoView.topAnchor.constraint(equalTo: view.topAnchor))
....
landscapeConstraints.append(collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

处理设备旋转:

// disable all constraints first
for constraint in self.portraitConstraints {
constraint.isActive = false
print("before: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
constraint.isActive = false
print("before: landscapeConstraint: \(constraint)")
}

// enable these after rotation
if UIDevice.current.orientation.isLandscape {
// gw: note: always disable previous rules first, then do enabling new rules
// implications: if you enable new rule first, you will have a short time period with conflicting rules

for constraint in self.landscapeConstraints {
constraint.isActive = true
}

for constraint in self.portraitConstraints {
print("after: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
print("after: landscapeConstraint: \(constraint)")
}

// not working if set here

collectionViewFlowLayout.scrollDirection = .vertical
} else {
for constraint in self.portraitConstraints {
constraint.isActive = true
}

for constraint in self.portraitConstraints {
print("after: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
print("after: landscapeConstraint: \(constraint)")
}

collectionViewFlowLayout.scrollDirection = .horizontal
}

它有效,但有时我会在控制台中观察到冲突约束错误。

所以我的问题是我是应该删除约束还是只禁用它们来处理方向变化?

完整代码在最后(没那么长):

import UIKit

class ViewController: UICollectionViewController{

let collectionViewCellIdentifier = "MyCollectionViewCellIdentifier"
let canvas:Canvas = {
let canvas = Canvas()
canvas.backgroundColor = UIColor.black
canvas.translatesAutoresizingMaskIntoConstraints=false
canvas.alpha = 0.2
return canvas
} ()

let photoView: UIImageView = {
let imageView = UIImageView()

imageView.image = UIImage(imageLiteralResourceName: "hongjinbao")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
} ()


private let myArray: NSArray = ["First","Second","Third"]

var portraitConstraints = [NSLayoutConstraint]()

var landscapeConstraints = [NSLayoutConstraint]()

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

// stack views
view.addSubview(photoView)
view.addSubview(canvas)

collectionView?.backgroundColor = UIColor.white
collectionView?.translatesAutoresizingMaskIntoConstraints = false

collectionView?.register(PersonCollectionViewCell.self, forCellWithReuseIdentifier: collectionViewCellIdentifier)


setupLayout()

// initial adjusting orientation

DispatchQueue.main.async {

self.adjustLayout()
}

}

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {



self.adjustLayout()

}

private func setupLayout() {

// MARK: - portrait constraints
guard let collectionView = collectionView else {
NSLog("failed to unwrap collectionView")
return

}


portraitConstraints.append(photoView.topAnchor.constraint(equalTo: view.topAnchor))
portraitConstraints.append(photoView.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1.333))
portraitConstraints.append(photoView.leadingAnchor.constraint(equalTo: view.leadingAnchor))
portraitConstraints.append(photoView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

portraitConstraints.append(canvas.topAnchor.constraint(equalTo: photoView.topAnchor))
portraitConstraints.append(canvas.bottomAnchor.constraint(equalTo: photoView.bottomAnchor))
portraitConstraints.append(canvas.leadingAnchor.constraint(equalTo: photoView.leadingAnchor))
portraitConstraints.append(canvas.trailingAnchor.constraint(equalTo: photoView.trailingAnchor))

portraitConstraints.append(collectionView.topAnchor.constraint(equalTo: photoView.bottomAnchor))
portraitConstraints.append(collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor))
portraitConstraints.append(collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor))
portraitConstraints.append(collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

for constraint in portraitConstraints {
constraint.isActive = false
print("portraitConstraint: \(constraint)")
}

// MARK: - landscape constraints

landscapeConstraints.append(photoView.topAnchor.constraint(equalTo: view.topAnchor))
landscapeConstraints.append(photoView.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1.333))
landscapeConstraints.append(photoView.leadingAnchor.constraint(equalTo: view.leadingAnchor))
landscapeConstraints.append(photoView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

landscapeConstraints.append(canvas.topAnchor.constraint(equalTo: photoView.topAnchor))
landscapeConstraints.append(canvas.bottomAnchor.constraint(equalTo: photoView.bottomAnchor))
landscapeConstraints.append(canvas.leadingAnchor.constraint(equalTo: photoView.leadingAnchor))
landscapeConstraints.append(canvas.trailingAnchor.constraint(equalTo: photoView.trailingAnchor))

landscapeConstraints.append(collectionView.topAnchor.constraint(equalTo: view.topAnchor))
landscapeConstraints.append(collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor))
landscapeConstraints.append(collectionView.leadingAnchor.constraint(equalTo: photoView.trailingAnchor))
landscapeConstraints.append(collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

for constraint in landscapeConstraints {
constraint.isActive = false
print("landscapeConstraint: \(constraint)")
}
}

private func adjustLayout() {
guard let collectionViewFlowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
NSLog("failed to convert layout as flow layout")

return

}


for constraint in self.portraitConstraints {
constraint.isActive = false
print("before: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
constraint.isActive = false
print("before: landscapeConstraint: \(constraint)")
}


// DispatchQueue.main.async {
if UIDevice.current.orientation.isLandscape {
// gw: note: always disable previous rules first, then do enabling new rules
// implications: if you enable new rule first, you will have a short time period with conflicting rules


for constraint in self.landscapeConstraints {
constraint.isActive = true
}

for constraint in self.portraitConstraints {
print("after: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
print("after: landscapeConstraint: \(constraint)")
}



// not working if set here

collectionViewFlowLayout.scrollDirection = .vertical


} else {

for constraint in self.portraitConstraints {
constraint.isActive = true
}

for constraint in self.portraitConstraints {
print("after: portraitConstraints: \(constraint)")
}

for constraint in self.landscapeConstraints {
print("after: landscapeConstraint: \(constraint)")
}



collectionViewFlowLayout.scrollDirection = .horizontal
}
// }

self.collectionView?.collectionViewLayout.invalidateLayout()
}

}


// MARK: - UICollectionViewDataSource
extension ViewController {

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.collectionViewCellIdentifier, for: indexPath)
return cell
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 13
}


}

// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController : UICollectionViewDelegateFlowLayout {

// set item size
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {

// gw: to force one row, height need to be smaller than flow height
return CGSize(width: 200, height: collectionView.bounds.height)
}
}

有关约束冲突的错误:

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2019-01-19 23:05:49.689599-0800 CelebScope[50076:5888826] [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:0x600001ae14f0 UIImageView:0x7ffe79e0d510.width == 1.333*UICollectionViewControllerWrapperView:0x7ffe79e12190.height (active)>",
"<NSLayoutConstraint:0x600001ae1540 H:|-(0)-[UIImageView:0x7ffe79e0d510] (active, names: '|':UICollectionViewControllerWrapperView:0x7ffe79e12190 )>",
"<NSLayoutConstraint:0x600001ae17c0 H:[UIImageView:0x7ffe79e0d510]-(0)-[UICollectionView:0x7ffe7a06da00] (active)>",
"<NSLayoutConstraint:0x600001ae1810 UICollectionView:0x7ffe7a06da00.trailing == UICollectionViewControllerWrapperView:0x7ffe79e12190.trailing (active)>",
"<NSLayoutConstraint:0x600001af50e0 'UIView-Encapsulated-Layout-Height' UICollectionViewControllerWrapperView:0x7ffe79e12190.height == 736 (active)>",
"<NSLayoutConstraint:0x600001af5090 'UIView-Encapsulated-Layout-Width' UICollectionViewControllerWrapperView:0x7ffe79e12190.width == 414 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600001ae17c0 H:[UIImageView:0x7ffe79e0d510]-(0)-[UICollectionView:0x7ffe7a06da00] (active)>

我在激活一组约束之前禁用了所有约束,但我不确定为什么它仍然报告约束冲突。

最佳答案

我认为没有问题所以不要删除它们,而是让它们共享

portraitConstraints.append(canvas.topAnchor.constraint(equalTo: photoView.topAnchor))
portraitConstraints.append(canvas.bottomAnchor.constraint(equalTo: photoView.bottomAnchor))
portraitConstraints.append(canvas.leadingAnchor.constraint(equalTo: photoView.leadingAnchor))
portraitConstraints.append(canvas.trailingAnchor.constraint(equalTo: photoView.trailingAnchor))

&

landscapeConstraints.append(canvas.topAnchor.constraint(equalTo: photoView.topAnchor))
landscapeConstraints.append(canvas.bottomAnchor.constraint(equalTo: photoView.bottomAnchor))
landscapeConstraints.append(canvas.leadingAnchor.constraint(equalTo: photoView.leadingAnchor))
landscapeConstraints.append(canvas.trailingAnchor.constraint(equalTo: photoView.trailingAnchor))

还有你指定的风景中的冲突

landscapeConstraints.append(photoView.widthAnchor.constraint(equalTo: view.heightAnchor,   multiplier: 1.333)) 
landscapeConstraints.append(photoView.leadingAnchor.constraint(equalTo: view.leadingAnchor))
landscapeConstraints.append(photoView.trailingAnchor.constraint(equalTo: view.trailingAnchor))

leading with trailing not equal to the multiplier width ,所以我猜你的意思是横向

landscapeConstraints.append(photoView.topAnchor.constraint(equalTo: view.topAnchor))
landscapeConstraints.append(photoView.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1.333))
landscapeConstraints.append(photoView.leadingAnchor.constraint(equalTo: view.leadingAnchor))
landscapeConstraints.append(photoView.bottomAnchor.constraint(equalTo: view.bottomAnchor))

关于ios - 当设备方向改变时,我应该禁用或删除布局约束吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54277731/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com