内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
设备旋转时是否可以更改约束条件?这可能如何实现?
一个简单的例子可能是两张图像,纵向堆叠,另一张堆叠在一起,但横向并排。
如果这是不可能的,我可以怎样做到这种布局?
我正在构建代码中的视图和约束,而不是使用接口构建器。
覆盖updateViewConstraints
方法UIViewController
为特定情况提供布局约束。这样,布局总是根据实际情况来设置正确的方式。确保它们与故事板中创建的约束一起形成完整的约束。可以使用IB设置一般约束,并将要更改的对象标记为在运行时删除。
我使用以下实现为每个方向提供了一组不同的约束:
-(void)updateViewConstraints { [super updateViewConstraints]; // constraints for portrait orientation // use a property to change a constraint's constant and/or create constraints programmatically, e.g.: if (!self.layoutConstraintsPortrait) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } // constraints for landscape orientation // make sure they don't conflict with and complement the existing constraints if (!self.layoutConstraintsLandscape) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation); [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait]; [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape]; }
现在,只要情况发生变化,就只需触发约束更新即可。覆盖willAnimateRotationToInterfaceOrientation:duration:
若要对方向更改进行约束更新,请执行以下操作:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; [self.view setNeedsUpdateConstraints]; }
为了避免狗血的故事板警告,我把所有的一组放在999的优先级上,这样它在任何地方都不会显示红色。
然后我将所有约束添加到出口集合中:
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;
最后,我执行我的ViewControllers
的viewWillLayout
method:
- (void) viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
for (NSLayoutConstraint *constraint in self.portraitConstraints) {
constraint.active = (UIApplication.sharedApplication.statusBarOrientation == UIDeviceOrientationPortrait);
}
for (NSLayoutConstraint *constraint in self.landscapeConstraints) {
constraint.active = (UIApplication.sharedApplication.statusBarOrientation != UIDeviceOrientationPortrait);
}
}