我可以使用自动布局为横向和纵向方向提供不同的约束吗? [英] Can I use autolayout to provide different constraints for landscape and portrait orientations?

查看:115
本文介绍了我可以使用自动布局为横向和纵向方向提供不同的约束吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当设备旋转时,是否可以更改约束?这可能如何实现?



一个简单的例子可能是两个图像,纵向堆叠一个在另一个之上,但在风景是并排的。



如果这不可能,我还可以如何完成这个布局?



使用 href =https://developer.apple.com/library/ios/recipes/xcode_help-IB_adaptive_sizes/chapters/AboutAdaptiveSizeDesign.html =nofollow noreferrer> 类别 在Xcode 6中,您可以在Interface Builder中为特定大小类轻松设置不同的约束。大多数设备(例如所有当前的iPhone)在横向模式下都有一个垂直大小类别





这是一个比确定设备方向更好的概念。 >

话虽如此,如果你真的需要知道方向, UIDevice.currentDevice()。orientation






原始帖子



覆盖 UIViewController updateViewConstraints 方法为特定情况提供布局约束。这样,布局总是根据情况设置正确的方式。确保它们与故事板中创建的约束形成一组完整的约束。您可以使用IB设置一般约束,并标记要在运行时删除的更改。





我使用以下实现为每个方向提供一组不同的约束:

   - (void)updateViewConstraints {
[super updateViewConstraints];

//纵向方向的约束
//使用属性更改约束的常量和/或以编程方式创建约束,例如:
if(!self.layoutConstraintsPortrait){
UIView * image1 = self.image1;
UIView * image2 = self.image2;
self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@V:| - [image1] - [image2] - |选项: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]];
}

//横向定义的约束
//确保它们不与现有约束冲突和补充
if(!self.layoutConstraintsLandscape){
UIView * image1 = self.image1;
UIView * image2 = self.image2;
self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@H:| - [image1] - [image2] - |选项: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];

}


Is it possible to change the constraints when the device is rotated? How might this be achieved?

A simple example might be two images which, in portrait, are stacked one above the other, but in landscape are side-by-side.

If this is not possible, how else might I accomplish this layout?

I am constructing my views and constraints in code and not using interface builder.

解决方案

Edit: Using the new concept of Size Classes introduced in Xcode 6, you can easily setup different constraints for specific size classes in Interface Builder. Most devices (e.g. all current iPhones) have a Compact vertical size class in landscape mode.

This is a much better concept for general layout decisions than determining the device's orientation.

That being said, if you really need to know the orientation, UIDevice.currentDevice().orientation is the way to go.


Original post:

Override the updateViewConstraints method of UIViewController to provide layout constraints for specific situations. This way, the layout is always set up the correct way according to situation. Make sure they form a complete set of constraints with those created within the storyboard. You can use IB to set up your general constraints and mark those subject to change to be removed at runtime.

I use the following implementation to present a different set of constraints for each orientation:

-(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];        
}

Now, all you need to do is trigger a constraint update whenever the situation changes. Override willAnimateRotationToInterfaceOrientation:duration: to animate the constraint update on orientation change:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];

}

这篇关于我可以使用自动布局为横向和纵向方向提供不同的约束吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆