2013-05-24 14 views
6

Supponiamo di avere due visualizzazioni di testo. In modalità ritratto, voglio questi uno di seguito all'altro & In modalità orizzontale, voglio che questi siano affiancatiDue viste, una sotto l'altra in verticale e affiancate in orizzontale utilizzando i vincoli di layout

E 'possibile farlo usando i vincoli di layout in storyboard utilizzando autolayout? Se sì, allora come? In caso contrario, quale sarebbe l'altra soluzione migliore per raggiungere questo obiettivo.

iOS6 è il mio obiettivo versione

risposta

8

Ecco come si potrebbe procedere in codice.

Fondamentalmente è necessario:

a) configurare le appropriate NSLayoutConstraint s per l'orientamento dato in updateViewConstraints nel vostro UIViewController.

b) chiamare [self.view setNeedsUpdateConstraints] quando l'interfaccia ruota.

Di seguito è riportata un'implementazione di ViewController e una categoria su UIView con metodi di supporto.

@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 

mettere questo in 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 

Questo è 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

sto ottenendo questo errore: "No @interface visibile per 'UIView' dichiara il selettore 'constrainSubview: usingEdgeInsets:'" – Homam

+0

@Homam ha si aggiunge la categoria vincoli UIView troppo? –

+0

Per test ho creato un progetto di esempio con un'applicazione SingleView. Copiato l'intero codice su ViewController. – Homam

2

A mio parere il modo migliore per il layout di vista di viewController in più di un orientamento è quello di creare viste poche per ogni orientamento. Here ho trovato questo:

"Quando si aggiunge un controller della vista allo storyboard si tratta di una visualizzazione della chiamata che la vista container Aggiungi due viste alla vista del contenitore:... La vista verticale e una vista del paesaggio Set la dimensione della vista verticale e della vista orizzontale utilizza in modo appropriato la finestra di ispezione della dimensione Aggiungi pulsanti, più viste, etichette o altro per le viste verticale e orizzontale necessarie per l'applicazione, quindi quando l'orientamento cambia nasconde una vista e mostra l'altra. "

0

Si potrebbe raggiungere tale comportamento utilizzando solo Interface Builder. È necessario impostare alcuni vincoli con priorità diverse.

Vedere la mia risposta più dettagliata sull'argomento here. Inoltre ci sono uno screencast e un link a un'app di esempio che ho creato.

Problemi correlati