XCode:如何在横向和纵向模式之间更改视图布局

在纵向模式下,我从视图控制器的顶部到底部有四个视图(参见图像)。

纵向视图

然后我想在设备转换为横向时更改视图相对于彼此的位置(参见图2)。 景观

我希望视图4与视图2和3一起移动,并且它们都位于视图1下方。

一些布局条件:

  • 视图1以横向和纵向方式附加到视图控制器的顶部。
  • 视图4以纵向模式连接到视图控制器的左,右和底边距。
  • 视图2,3和4在纵向视图中水平居中。

实现不同布局的最佳方法是什么?

最优雅的解决方案是在视图控制器代码中引用约束并在viewWillTransition中激活和停用它们吗? 或者是否有一种方法可以使用各种特性来实现这一点(我可以想象水平居中的视图2,3和4会使这很难实现,以及在横向模式下为视图4添加新约束)?

我们过去常常设置不同的约束集,并根据方向变化激活/停用它们。 但是现在可以使用大小类和“因性状而异”。

例如,我从一个简单的视图开始,选择一个紧凑的宽度大小类,然后选择“Vary for traits”:

在此处输入图像描述

然后我添加适当的约束并单击“完成变化”:

在此处输入图像描述

然后我选择“常规宽度大小类”并重复该过程(“变化为特征”,添加约束,单击“完成变化”:

在此处输入图像描述

然后,您最终会得到一个场景,该场景将对紧凑宽度大小类和常规宽度大小类具有完全不同的约束集。 即,当我运行应用程序时,如果设备旋转,则会激活新约束:

在此处输入图像描述

有关更多信息,请参阅有关自适应布局的WWDC 2016video:

我使用约束数组并根据方向激活/停用。

var p = [NSLayoutConstraint]() var l = [NSLayoutConstraint]() var initialOrientation = true var isInPortrait = false override func viewDidLoad() { super.viewDidLoad() // add any subviews here view.turnOffAutoResizing() // add constraints here.... // common constraints you can set their isActive = true // otherwise, add in to portrait(p) and landscape(l) arrays } override func viewWillLayoutSubviews() { super.viewDidLayoutSubviews() if initialOrientation { initialOrientation = false if view.frame.width > view.frame.height { isInPortrait = false } else { isInPortrait = true } view.setOrientation(p, l) } else { if view.orientationHasChanged(&isInPortrait) { view.setOrientation(p, l) } } } extension UIView { public func turnOffAutoResizing() { self.translatesAutoresizingMaskIntoConstraints = false for view in self.subviews as [UIView] { view.translatesAutoresizingMaskIntoConstraints = false } } public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool { if self.frame.width > self.frame.height { if isInPortrait { isInPortrait = false return true } } else { if !isInPortrait { isInPortrait = true return true } } return false } public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) { NSLayoutConstraint.deactivate(l) NSLayoutConstraint.deactivate(p) if self.bounds.width > self.bounds.height { NSLayoutConstraint.activate(l) } else { NSLayoutConstraint.activate(p) } } } 

我需要区分肖像或风景需要使用大小类以外的东西,因为我的应用程序是通用的,iPad(除非使用拆分或滑出视图) 总是正常大小。 此外,您可以使用viewWillTransistion(toSize:)viewDidLoadSubviews()而不是’viewWillLoadSubviews()` – 但总是测试,因为这些可能会在方向更改时执行多次!