6

假设我有两个文本视图。在纵向模式下,我希望这些在另一个下方,在横向模式下,我希望这些并排

是否可以使用自动布局在情节提要中使用布局约束来做到这一点?如果是,那么如何?如果不是,那么实现这一目标的其他更好的解决方案是什么。

ios6是我的目标版本

4

3 回答 3

8

以下是您可以如何在代码中执行此操作。

基本上你需要:

a)NSLayoutConstraintupdateViewConstraints您的UIViewController.

b)[self.view setNeedsUpdateConstraints]界面旋转时调用。

下面是一个 ViewController 实现和 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
于 2013-05-24T09:30:51.170 回答
2

在我看来,在多个方向上布局 viewController 的视图的最佳方法是为每个方向创建几个视图。 这里我发现了这个:

“当您将视图控制器添加到情节提要时,它会附带一个视图。称之为容器视图。向容器视图添加两个视图:纵向视图和横向视图。适当地设置纵向视图和横向视图的尺寸“

于 2013-05-24T07:29:33.937 回答
0

您只能通过使用 Interface Builder 来实现这种行为。您需要设置一些具有不同优先级的约束。

在此处查看我关于该主题的更详细答案。还有一个截屏视频和指向我创建的示例应用程序的链接。

于 2013-11-21T11:49:04.117 回答