nhg*_*rif 29 uikit ios xcode-storyboard autolayout nslayoutconstraint
我经常遇到这个问题,我希望我的观点以一种方式排列为纵向,而对于景观则有一种截然不同的方式.
有关简化示例,请考虑以下事项:


请注意,在纵向上图像是垂直堆叠的,但在横向上,它们是并排的?
当然,我可以手动计算位置和大小,但对于更复杂的视图,这很快就会变得复杂.另外,我更喜欢使用Autolayout,因此设备特定的代码更少(如果有的话).但这似乎要写很多 Autolayout代码.有没有办法通过故事板为这类东西设置约束?
nhg*_*rif 33
Xcode的界面构建器有两个未充分利用的功能,我们可以利用这里使这类事物成为同步.
IBOutlet连接NSLayoutConstraints.IBOutlet对象数组.因此,考虑到这两点,我们想要做的就是为一个方向创建所有自动布局约束,将它们全部挂在插座集合中.现在,对于每个约束,取消选中界面构建器上的"已安装"选项.然后将我们的所有插座集合用于另一个布局,并将它们连接到另一个插座集合.我们可以根据需要创建尽可能多的布局组.
重要的是要注意我们需要对任何直接安装了约束的UI元素的引用,我们需要一个单独的插座集合,不仅适用于我们想要的每个布局,而且还需要直接在其上安装约束的每个UI对象. .
让我们看一下你问题中相当简单的例子.

如果您查看左侧的约束列表,您可以看到其中一半是灰显的.灰色约束是景观约束.我创建了所有这些,然后为每个人取消选中"Installed":

同时,未经修饰的,看起来很正常的约束是肖像约束.对于这些,我把它们"安装"了.保留其中任何一个都是完全没必要的,但如果你安装了多个套件(它们很可能会发生冲突),你会遇到问题.

请确保不要检查"在构建时删除"中的任何一个.我们不希望在构建时"删除"约束.这只是意味着根本没有创建约束(所以我们将失去对它的引用).如果我们IBOutlet在约束条件下标记了此检查,Xcode将生成警告:
不支持的配置
连接到占位符约束.在IB中标记为占位符的约束不应具有任何连接,因为这些约束不会编译到文档中,并且在运行时不会存在.
无论如何,现在我们需要将约束连接到插座,以便我们可以在运行时访问它们.
按住Ctrl并单击并从其中一个约束拖动到源代码文件,就像连接任何其他UI元素一样.在弹出的对话框中,选择Outlet Collection和描述性名称:

现在将与该约束组匹配的所有其他约束连接到同一个outlet集合中:

一旦我们完成了所有约束,只需在适当的时候删除/添加它们.
对于问题中描述的场景这样一个简单的例子,我们可以updateViewConstraints用这样的代码覆盖:
class ViewController: UIViewController {
@IBOutlet var landscapeConstraints: [NSLayoutConstraint]!
@IBOutlet var portraitConstraints: [NSLayoutConstraint]!
override func updateViewConstraints() {
let isPortrait = self.view.bounds.width < self.view.bounds.height
self.view.removeConstraints(self.portraitConstraints)
self.view.removeConstraints(self.landscapeConstraints)
self.view.addConstraints(isPortrait ? self.portraitConstraints : self.landscapeConstraints)
super.updateViewConstraints()
}
}
Run Code Online (Sandbox Code Playgroud)
@interface ViewController()
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@end
@implementation ViewController
- (void)updateViewConstraints {
BOOL isPortrait = self.view.bounds.size.width < self.view.boudns.size.height;
[self.view removeConstraints:self.portraitConstraints];
[self.view removeConstraints:self.landscapeConstraints];
[self.view addConstraints:(isPortrait ? self.portraitConstraints : self.landscapeConstraints)];
[super updateViewConstraints];
}
@end
Run Code Online (Sandbox Code Playgroud)
我们没有检查视图以前有哪些约束集,所以只需删除我们的两个约束集,然后添加我们想要使用的相应集.
这是我们需要管理的所有代码,在运行时完全更改对象的整个约束集.这允许在界面构建器中工作以设置我们所有的约束,而不是必须以编程方式执行它(我发现它更乏味且容易出错).
最终的结果?非常漂亮的自动旋转重新排列,而不会让你的头发完美地完成自动布局代码:

| 归档时间: |
|
| 查看次数: |
1897 次 |
| 最近记录: |