Autolayout and Constraints for iPad

时光毁灭记忆、已成空白 提交于 2020-01-03 05:51:04

问题


I'm quite confused about the new auto layout feature of xCode 4.5.

Here is I want to do,

By setting the storyboard, I have this portrait view set up.

By using autolayout and constraints(and pins), how can I transform the layout when its flipped to landscape like this?

I tried coding and changing the CGRect(size and coordinate location) of the views when its landscaped but to no avail.


回答1:


NSLayoutConstraints replace the need for CGRects in Auto Layout. First, describe your layout in words. Here's how I'd describe your portrait example:

  • Red's width is 60% of its superview's.
  • Blue's height is 55% of its superview's.
  • Blue's left & right edges are touching its superview's.
  • Red's left edge is touching its superview's, red's right edge is close to yellow's left edge, and yellow's right edge is touching its superview's.
  • Blue's top edge is touching its superview's, blue's bottom edge is close to red's top edge, and red's bottom edge is touching its superview's.
  • Blue's bottom edge is close to yellow's top edge, and yellow's bottom edge is touching its superview's.

Here's a method that removes superview's existing constraints, then applies new constraints for the given interface orientation.

- (void) buildConstriantsForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Remove existing constraints.
    [superview removeConstraints:superview.constraints] ;
    // Build an array to hold new constraints.
    NSMutableArray* constraints = [NSMutableArray new] ;

    // Add 2 constraints that apply to both Portrait & Landscape orientations.
    [constraints addObject:[NSLayoutConstraint constraintWithItem:red  attribute:NSLayoutAttributeWidth  relatedBy:NSLayoutRelationEqual  toItem:superview  attribute:NSLayoutAttributeWidth  multiplier:0.6  constant:0]] ;
    [constraints addObject:[NSLayoutConstraint constraintWithItem:blue  attribute:NSLayoutAttributeHeight  relatedBy:NSLayoutRelationEqual  toItem:superview  attribute:NSLayoutAttributeHeight  multiplier:0.55  constant:0]] ;

    // Build a dictionary to store references to NSViews.
    NSDictionary* views = NSDictionaryOfVariableBindings(superview, blue, red, yellow) ;
    // To eliminate repeated NSLayoutConstraint code, build an array of Format Strings with which to build constraints.
    NSArray* formatStrings ;
    if ( UIInterfaceOrientationIsPortrait(interfaceOrientation) ) {
        formatStrings = @[@"H:|[blue]|", @"H:|[red]-[yellow]|", @"V:|[blue]-[red]|", @"V:[blue]-[yellow]|"] ;
    }
    else {
        formatStrings = @[@"H:|[blue]-[yellow]|", @"H:|[red]-[yellow]", @"V:|[blue]-[red]|", @"V:|[yellow]|"] ;
    }

    for ( NSString* formatString in formatStrings ) {
        [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString  options:0  metrics:nil  views:views]] ;
    }

    // Add the newly created constraints.
    [superview addConstraints:constraints] ;
}

You can call that method whenever the view loads or rotates.

-(void) viewDidLoad {
    superview.translatesAutoresizingMaskIntoConstraints = NO ;
    [self buildConstriantsForInterfaceOrientation:self.interfaceOrientation] ;
}

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self buildConstriantsForInterfaceOrientation:toInterfaceOrientation] ;
}



回答2:


Autolayout is great at expressing the relation of one object to another and resolving conflicts - but it doesn't have any conditional concepts built in. For your layout I think you may find it easiest to add and remove constraints on rotation, check out https://developer.apple.com/library/ios/#documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html for the details on how to add those.

You can also set up your constraints and adjust the priorities so that it does the right thing on rotation but it will take some testing and adjustment to get it right on. I did some testing locally and I think I have it doing the right thing but that's just with empty views that have no inherent content size. Nevertheless, here is what I think is required to do it all via storyboard:

  • Make sure the blue view has a width <= the portrait width and >= the minimum landscape width
  • Make sure the red view has a minimum height
  • Fix the yellow view's width, and set the height to be >= the portrait height
  • Anchor each view to the corner it will always remain in (eg, pin trailing and bottom to superview for yellow)
  • Align the top of the yellow view with the blue view, with a low priority
  • Increase content compression resistance for yellow

I think of it as starting with the blue view having a fairly high priority maximum size, and the yellow view knowing how to expand upwards but being low priority. When it rotates, the blue view keeps its maximum size which frees the yellow view to expand upwards. Then I fill in the needed constraints to keep things aligned.

This is fairly complicated to describe in text, here is a screengrab showing the three views and the constraints between them. It doesn't show everything, but you can at least inspect the relations between the views:



来源:https://stackoverflow.com/questions/16730720/autolayout-and-constraints-for-ipad

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!