2013-05-24 9 views

Odpowiedz

8

Oto, jak możesz to zrobić w kodzie.

Zasadniczo trzeba:

a) skonfigurować odpowiednie NSLayoutConstraint s dla danej orientacji w updateViewConstraints w UIViewController.

b) zadzwoń pod numer [self.view setNeedsUpdateConstraints] po obróceniu interfejsu.

Poniżej znajduje się implementacja ViewController i kategoria na UIView przy pomocy metod pomocniczych.

@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 

umieścić to w 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 

To 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

ja dostaję ten błąd: „Brak widocznych @interface dla«UIView»deklaruje selektor«constrainSubview: usingEdgeInsets:»” – Homam

+0

@Homam pan dodać na UIView zbyt kategorię ograniczeń? –

+0

Aby przetestować utworzony przykładowy projekt z aplikacją SingleView. Skopiowałem cały twój kod do ViewController. – Homam

2

Moim zdaniem najlepszym sposobem na układ widoki viewController w więcej niż jednej orientacji jest stworzenie kilku widoków dla każdej orientacji. Here Znalazłem to:

„Po dodaniu kontrolera widoku do ujęć pochodzi z myślą Zadzwoń że widok pojemnik Dodaj dwa widoki do widoku kontenera... W widoku pionowym i widoku poziomym Set Wymiar widoku pionowego i widoku poziomego odpowiednio za pomocą kontrolera rozmiaru Dodaj przyciski, więcej widoków, etykiet lub cokolwiek do widoków pionowych i poziomych zgodnie z potrzebami aplikacji, a następnie, gdy zmiany orientacji ukryją jeden widok i pokaż drugi. "

0

Można osiągnąć takie zachowanie za pomocą tylko interfejsu Builder. Musisz ustawić pewne ograniczenia o różnych priorytetach.

Zobacz moją bardziej szczegółową odpowiedź na temat here. Jest też screencast i link do przykładowej aplikacji, którą utworzyłem.