在纵向排列时,两个视图一个在另一个下方;在横向排列时,两个视图并排放置。使用布局约束实现。

6

假设我有两个文本视图。 在纵向模式下,我想让它们一个在另一个下面; 在横向模式下,我想让它们并排。

是否可以使用故事板中的布局约束和自动布局来实现这一点? 如果可以,怎么做? 如果不行,那么有什么更好的解决方案可以实现这一点。

我的目标版本是ios6。

3个回答

8
以下是如何在代码中进行操作。
基本上你需要:
a) 在你的UIViewController中的updateViewConstraints方法中为给定方向配置适当的NSLayoutConstraint
b) 当界面旋转时调用[self.view setNeedsUpdateConstraints]
下面是一个视图控制器实现和UIView帮助方法的类别。
@interface ConstraintsViewController ()

@property (nonatomic, weak) IBOutlet UIView  *upperOrLeftView, *lowerOrRightView;

@end


@implementation ConstraintsViewController

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self.view setNeedsUpdateConstraints];
}

-(void)updateViewConstraints {
    [super updateViewConstraints];

    [self.view removeConstraintsRelatingToItems:@[self.upperOrLeftView,self.lowerOrRightView]];

    if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
        [self.view constrainSubview:self.upperOrLeftView usingEdgeInsets:UIEdgeInsetsMake(0, 0, -1, 0)];
        [self.view constrainSubview:self.lowerOrRightView usingEdgeInsets:UIEdgeInsetsMake(-1, 0, 0, 0)];
        [self.view constrainSubviewsTopToBottom:@[self.upperOrLeftView, self.lowerOrRightView]];
    }
    else {
        [self.view constrainSubview:self.upperOrLeftView usingEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -1)];
        [self.view constrainSubview:self.lowerOrRightView usingEdgeInsets:UIEdgeInsetsMake(0, -1, 0, 0)];
        [self.view constrainSubviewsLeftToRight:@[self.upperOrLeftView, self.lowerOrRightView]];
    }
}

@end

把这个放在UIView+Constraints.h文件中。
@interface UIView (Constraints)

-(void)removeConstraintsRelatingToItems:(NSArray*)items;

-(void)constrainSubview:(UIView*)subview usingEdgeInsets:(UIEdgeInsets)insets;

-(void)constrainSubviewsLeftToRight:(NSArray*)subviews;

-(void)constrainSubviewsTopToBottom:(NSArray*)subviews;

@end

这是 UIView+Constraints.m 文件。
@implementation UIView (Constraints)

-(void)removeConstraintsRelatingToItems:(NSArray *)items {
    for(NSLayoutConstraint *constraint in self.constraints) {
        if([items containsObject:constraint.firstItem] || [items containsObject:constraint.secondItem]) {
            [self removeConstraint:constraint];
        }
    }
}

/** Set up constraints to flow the subviews from top to bottom and with equal heights */
-(void)constrainSubviewsTopToBottom:(NSArray*)subviews {
    if(subviews.count > 1) {
        UIView *anchorView = subviews[0];
        for(int i = 1; i < subviews.count; i++) {
            UIView *view = subviews[i];
            NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:anchorView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0];
            NSLayoutConstraint *edgesConstraint = [NSLayoutConstraint constraintWithItem:anchorView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
            [self addConstraints:@[heightConstraint, edgesConstraint]];
            anchorView = view;
        }
    }
}

/** Set up constraints to flow the subviews from left to right and with equal widths */
-(void)constrainSubviewsLeftToRight:(NSArray*)subviews {
    if(subviews.count > 1) {
        UIView *anchorView = subviews[0];
        for(int i = 1; i < subviews.count; i++) {
            UIView *view = subviews[i];
            NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:anchorView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];
            NSLayoutConstraint *edgesConstraint = [NSLayoutConstraint constraintWithItem:anchorView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
            [self addConstraints:@[widthConstraint, edgesConstraint]];
            anchorView = view;
        }
    }
}

/**
 Set up constraints to anchor the various edges of the subview to it's superview (this view) using the provided insets.
 Any inset set to < 0.0 means that edge is ignored;
 */
-(void)constrainSubview:(UIView*)subview usingEdgeInsets:(UIEdgeInsets)insets {
    if(insets.top >= 0.0) {
        [self addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:insets.top]];
    }

    if(insets.right >= 0.0) {
        [self addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-insets.right]];
    }

    if(insets.bottom >= 0.0) {
        [self addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-insets.bottom]];
    }

    if(insets.left >= 0.0) {
        [self addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:insets.left]];
    }
}

@end

是的,我已经复制了整个代码,包括ConstraintsViewController和UIView(Constraints)。 - Homam
你是否将类别放在自己的文件中,并在你的ViewController中导入了头文件? - Mike Pollard
Mike Pollard,这正是我在寻找的。谢谢! - Ben Wheeler
考虑在viewWillAppear中调用setNeedsUpdateConstraints - 例如,视图可能在模态窗口中隐藏时被旋转。 - Ben Packard
你有没有想过如何让你的应用程序在iPhone和iPad上运行?在iPad上,你可以将4个视图并排放置...是否有一些变量取决于屏幕的宽度或高度? - Yoko
显示剩余4条评论

2
在我看来,为了在多个方向上布局viewController的视图,最好的方法是为每个方向创建几个视图。在这里,我找到了以下内容:
"当您将视图控制器添加到故事板中时,它会带有一个视图。将其称为容器视图。向容器视图添加两个视图:一个纵向视图和一个横向视图。使用大小检查器适当地设置纵向视图和横向视图的尺寸。根据应用程序的需要,向纵向和横向视图添加按钮、更多视图、标签或其他内容。然后当方向改变时,隐藏一个视图并显示另一个视图。"

0

您可以仅使用Interface Builder实现此类行为。您需要设置一些具有不同优先级的约束。

请查看我在这里上对该主题的更详细回答。此外,还有一个屏幕录像和一个我创建的示例应用程序的链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接