2013-05-24 1 views
6

Предположим, у меня есть два вида текста. В портретном режиме, я хочу это одна ниже другой & В ландшафтном режиме, я хочу, чтобы они были рядомДва вида, один под другим в портретном и бок о бок в ландшафте с использованием ограничений макета

Можно ли сделать это с помощью ограничения макета в раскадровке с помощью autolayout? Если да, то как? Если нет, то каково было бы лучшее решение для этого.

iOS6 моя целевая версия

ответ

8

Вот как вы можете это сделать в коде.

В основном вам нужно:

а) настроить соответствующие NSLayoutConstraint с для данной ориентации в updateViewConstraints в вашем 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 
+0

Я получаю эту ошибку: «Нет видимых @interface для„UIView“не декларирует селектор 'constrainSubview: usingEdgeInsets:» – Homam

+0

@Homam вы добавить категорию ограничений на UIView тоже? –

+0

Чтобы проверить, я создал образец проекта с помощью приложения SingleView. Скопировал весь код в ViewController. – Homam

2

На мой взгляд, лучший способ макет взгляды ViewController в более чем одной ориентации, чтобы создать несколько представлений для каждой ориентации. Here я нашел это:

«Когда вы добавляете контроллер представления в раскадровке он приходит с видом Позвоните, чтобы вид контейнера Добавить два вида в вид контейнера:... В портретном и альбомную Set размер портретного вида и пейзажного вида, подходящий с помощью инспектора размера. Добавьте кнопки, больше видов, ярлыков или что-либо другое в портретные и пейзажные виды, необходимые для вашего приложения. Затем, когда изменения ориентации скроют один вид и покажут другой. "

0

Вы могли бы достичь такого поведения, используя только Interface Builder. Вам нужно настроить некоторые ограничения с разными приоритетами.

См. Мой более подробный ответ на тему here. Также есть скринкаст и ссылка на пример приложения, которое я создал.

Смежные вопросы