【问题标题】:Two views, one below another in portrait and side by side in landscape using layout constraints两个视图,一个在纵向下方,横向并排使用布局约束
【发布时间】:2013-05-19 17:17:28
【问题描述】:

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

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

ios6 是我的目标版本

【问题讨论】:

    标签: iphone ios ios6 storyboard nslayoutconstraint


    【解决方案1】:

    以下是您可以在代码中执行的方法。

    基本上你需要:

    a) 在UIViewController 中为updateViewConstraints 中的给定方向配置适当的NSLayoutConstraints。

    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
    

    【讨论】:

    • 我收到此错误:“'UIView' 没有可见的@interface 声明选择器'constrainSubview:usingEdgeInsets:'”
    • @Homam 你是否也在 UIView 上添加了约束类别?
    • 为了测试我使用 SingleView 应用程序创建了示例项目。将您的整个代码复制到 ViewController。
    • 你也需要取 UIView(Constraints) 类别。
    • 是的,我已经复制了整个代码,包括 ConstraintsViewController & UIView(Constraints)
    【解决方案2】:

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

    “当您将视图控制器添加到情节提要时,它会附带一个视图。称为容器视图。向容器视图添加两个视图:纵向视图和横向视图。设置纵向视图的尺寸和使用尺寸检查器适当地使用横向视图。根据应用程序的需要向纵向和横向视图添加按钮、更多视图、标签或其他内容。然后当方向更改时隐藏一个视图并显示另一个视图。"

    【讨论】:

      【解决方案3】:

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

      请参阅我对主题here 的更详细回答。还有一个截屏视频和一个指向我创建的示例应用程序的链接。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-28
        • 1970-01-01
        • 2011-04-03
        • 1970-01-01
        • 2017-05-07
        • 2011-01-12
        • 2015-03-22
        • 1970-01-01
        相关资源
        最近更新 更多