2/24/15

iOS Autolayout Constraints on Stacked Views



The containing view (gray border) vertically resizes to fit child views.
Containing view is hidden when child view heights total 0.

5 screenshots
1. View layout before applying constraints
2. 3 child views, heights 100
3. Green view height 0
4. Green and blue view height 0
5. Red view height 20, green view height 40


@implementation ViewController
{
    UIView * cv;  //container view, clear w/gray border
    UIView * tv;  //top view, red
    UIView * mv;  //middle view, green
    UIView * bv;  //bottom view, blue

    NSDictionary * bindings;
    NSMutableArray * verticalConstraints;
}

-(void)viewDidLoad
{
    [super viewDidLoad];

    [self createControls];
    [self setupConstraints];
}

-(void)setupConstraints
{
    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    cv.translatesAutoresizingMaskIntoConstraints = NO;
    tv.translatesAutoresizingMaskIntoConstraints = NO;
    mv.translatesAutoresizingMaskIntoConstraints = NO;
    bv.translatesAutoresizingMaskIntoConstraints = NO;

    bindings = NSDictionaryOfVariableBindings(cv, tv, mv, bv);
    verticalConstraints = [NSMutableArray array];

    [self setupHorizontalConstraints];
    [self setupVerticalConstraints];
}

-(void)setupHorizontalConstraints
{
    NSMutableArray * hConstraints = [NSMutableArray array];
    
    //container view
    [hConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[cv(200)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:bindings]];
    //top view
    [hConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[tv]-|"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:bindings]];
    //match middle view w/top view
    [hConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[mv(tv)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:bindings]];
    //match bottom view w/top view
    [hConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[bv(tv)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:bindings]];
    [self.view addConstraints:hConstraints];
}

-(void)setupVerticalConstraints
{
    [self.view removeConstraints:verticalConstraints];
    [verticalConstraints removeAllObjects];

    [verticalConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[cv]-20-|"
                                                                                     options:0
                                                                                     metrics:nil
                                                                                       views:bindings]];
    //view heights, container vertical margin
    NSDictionary * metrics = @{ @"th" : @(tv.frame.size.height),
                                @"mh" : @(mv.frame.size.height),
                                @"bh" : @(bv.frame.size.height),
                                @"cm" : @(tv.frame.size.height + mv.frame.size.height + bv.frame.size.height > 0 ? 8 : 0) };

    [verticalConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-cm-[tv(th)][mv(mh)][bv(bh)]-cm-|"
                                                                                     options:NSLayoutFormatAlignAllCenterX
                                                                                     metrics:metrics
                                                                                       views:bindings]];
    [self.view addConstraints:verticalConstraints];
}

//init controls w/temp width and position for general layout, before implementing constraints
-(void)createControls
{
    int vWidth  = 100;
    int vHeight = 100;
    int cHeight = vHeight * 3;

    cv = [[UIView alloc] initWithFrame:CGRectMake(20,  20, vWidth, cHeight)];
    tv = [[UIView alloc] initWithFrame:CGRectMake(10,   0, vWidth, vHeight)];
    mv = [[UIView alloc] initWithFrame:CGRectMake(10, 100, vWidth, vHeight)];
    bv = [[UIView alloc] initWithFrame:CGRectMake(10, 200, vWidth, vHeight)];
    
    cv.layer.borderColor = [UIColor lightGrayColor].CGColor;
    cv.layer.borderWidth = 1;

    tv.backgroundColor = [UIColor redColor];
    mv.backgroundColor = [UIColor greenColor];
    bv.backgroundColor = [UIColor blueColor];

    [self.view addSubview:cv];
    [cv addSubview:tv];
    [cv addSubview:mv];
    [cv addSubview:bv];
}


-(void)hideView:(UIView *)aView
{
    aView.frame = CGRectMake(0, 0, aView.frame.size.width, 0);
    [self setupVerticalConstraints];
}

-(void)resizeView:(UIView *)aView height:(int)aHeight
{
    aView.frame = CGRectMake(0, 0, aView.frame.size.width, aHeight);
    [self setupVerticalConstraints];
}

-(void)showView:(UIView *)aView
{
    aView.frame = CGRectMake(0, 0, aView.frame.size.width, 100);
    [self setupVerticalConstraints];
}

No comments:

Post a Comment