【发布时间】:2021-09-15 07:53:26
【问题描述】:
我有一个相对简单的布局,它分为两个主要部分,我用两个UIViews 将其包含在内,以便于管理。
我的目标是提供两种不同的布局,一种用于纵向,一种用于横向。
我的第一个想法是对“宽度”和“高度”都使用“Vary for Traits”,因此,我将情节提要设置为纵向模式,单击“Vary for Traits”,我应用了我想要的特征在纵向模式下,单击“完成”,切换到横向模式并重复该过程。
如您所见,在情节提要中切换方向效果很好
除了,当我在设备上运行它时......它不工作......正如预期的那样
好的????,所以我想,我回去再做一次,但这一次只是改变“宽度”,再一次,它不起作用。
所以,我当时想,我会去老学校。我会添加每个约束并为特定尺寸类设置一个变体......
(我对两个方向都有不同的约束,因此单个约束对两个方向都没有变体)
而且......再一次,这不起作用。在有人告诉我需要在两个方向上勾选“已安装”之前,不,它没有,这只会让 Xcode 生气并在控制台中吐出很多讨厌的 cmets。
“问题”
那么,“简单”的问题是,我做错了什么?我是否错过了一些非常明显的东西可以使这项工作,或者对肖像和风景有单独的约束只是一个非常愚蠢的想法(我虽然“Vary for Traits”基本上是这样做的)
一个“hacky”解决方法
因此,在花了很多时间在这之后,我又回到了过去用于手动创建 UI 的旧“工作流程”
从为每个变体手动创建的约束点开始,我基本上将所有横向和纵向约束放入单独的 IBOutlet 集合中,当调用 viewWillTransition 时,手动取消/激活所需的约束组...
class ViewController: UIViewController {
@IBOutlet var landscapeConstraints: [NSLayoutConstraint]!
@IBOutlet var portraitConstraints: [NSLayoutConstraint]!
override func viewDidLoad() {
super.viewDidLoad()
}
enum Orientation {
case landscape
case portrait
case unknown
}
fileprivate var lastOrientation: Orientation = .unknown
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
updateCurrentConstraints(toSize: view.bounds.size)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate { (ctx) in
self.updateCurrentConstraints(toSize: size)
} completion: { (ctx) in
}
}
func updateCurrentConstraints(toSize size: CGSize) {
var orientation: Orientation = .portrait
if size.width > size.height {
orientation = .landscape
}
guard orientation != lastOrientation else { return }
lastOrientation = orientation
guard let portraitConstraints = portraitConstraints, let landscapeConstraints = landscapeConstraints else {
print("No constraits")
return
}
var activeConstraints = portraitConstraints
var inactiveConstraints = landscapeConstraints
if orientation == .landscape {
activeConstraints = landscapeConstraints
inactiveConstraints = portraitConstraints
}
for constraint in inactiveConstraints {
constraint.isActive = false
}
for constraint in activeConstraints {
constraint.isActive = true
}
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
}
这行得通,我希望它没有,我希望我刚刚做了一些非常愚蠢的事情......除了hacky解决方法
如果您没有太多事情可做并且想搞砸它,有一个 source repo 我用来测试这个概念并提出我的“超级、很棒”的解决方法,我很感激任何类型的情节提要相关问题都是......代码的完整痛苦
【问题讨论】:
-
“这行得通,我希望它没有,我希望我刚刚做了一些非常愚蠢的事情......除了hacky解决方法”这不是hacky。这是非常标准的,我建议您这样做并感到高兴。 :)
-
我玩过你的源代码库(帮助很多!),我注意到了一些事情:如果你在 Storyboard 中使用 iPhone Pro Max,它将具有 RxC 和 CxR 大小类.但是,如果您在更小尺寸的设备上进行测试,它将具有横向 CxC。在模拟器中运行 Pro Max 似乎没有问题。你尝试过这些不同的场景吗?
-
是的,可能有助于在这里学习信息表stackoverflow.com/questions/52317545/…
-
@JoshGrant 这是一些巧妙的建议。为了记录,我在故事板和设备上都使用 iPhone 11" ...因为,理智:P
标签: ios swift xcode storyboard