Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have just started using Auto Layout for my latest project and I was wondering what would be the most efficient way of laying out the following table cell:

UITableCell: the various necessary views are shown in black

Views A and B are both UILabels. C is a fixed size image and the view under A is an image that may or not be present. I am able to easily lay out A, B and C. But if the image under A is present, A's height needs to shrink proportionately and the image needs to fit underneath so that both are centered horizontally in the contentView.

I am trying to lay the entire cell out using code and the Visual Format language and have gotten quite close so far. The only problem is that the A and it's accompanying image aren't centered vertically in the container. You can see how far I have gotten in the image below:

Layout using a combination of the Visual Format Language and some extra constraints

And here is the code that I am using in my updateConstraints method. Note that with this code, I don't get an ambiguous layout:

NSDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB, viewC);
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[viewA]-[viewB]-(>=8)-[viewC]-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];


    NSDictionary *metrics = @{@"width":@(40.0f), @"height":@(40.0f), @"priority":@(UILayoutPriorityRequired)};

    [viewC addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewC(==width@priority)]"
                                                                          options:0
                                                                          metrics:metrics
                                                                            views:@{@"viewC": _merchantLogo}]];
    [viewC addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewC(==height@priority)]"
                                                                          options:0
                                                                          metrics:metrics
                                                                            views:views]];

    [viewA addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewA(>=75@750)]"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:views]];

    [viewB addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewB(>=115@500)]"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:views]];

    [self.contentView addConstraints:@[[NSLayoutConstraint constraintWithItem:viewC
                                                                    attribute:NSLayoutAttributeCenterY
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:self.contentView
                                                                    attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f],
                                       [NSLayoutConstraint constraintWithItem:viewB
                                                                    attribute:NSLayoutAttributeCenterY
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:self.contentView
                                                                    attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]]];

    if (!viewD) {
        [self.contentView addConstraints:@[[NSLayoutConstraint constraintWithItem:viewA
                                                                        attribute:NSLayoutAttributeCenterY
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.contentView
                                                                        attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]]];
    } else {
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewA][viewD]"
                                                                                 options:NSLayoutFormatAlignAllLeft
                                                                                 metrics:nil
                                                                                   views:NSDictionaryOfVariableBindings(viewA, viewD)]];
    }

One of my ideas was to put A and the image below it in a container view and then lay them out within that view. But that seems kind of inefficient and I first want to make sure this isn't possible without using a container view.

share|improve this question

1 Answer

up vote 2 down vote accepted

enter image description here

So...

1.
Format
@"|-[_viewA(<=75)]-[viewB]-[viewC(==60)]-|"
Options
NSLayoutFormatAlignAllTop

2.
Format
@"V:|-[viewA]-[imageView(==10)]-|"
Options
NSLayoutFormatAlignCenterX | NSLayoutFormatAlignAllLeft

3.
Add individual constraints to constrain bottom of image view to bottom of viewB and viewC.
[NSLayotuConstraint constraintWithItem:viewB
                             attribute:NSLayoutAttributeBottom
                             relatedBy:NSLayoutRelationEqual
                                toItem:imageView
                             attribute:NSLayoutAttributeBottom
                            multiplier:1.0
                              constant:0];

and other one...

This should give you what you want.

share|improve this answer
1  
This is almost perfect! Thanks a bunch. The one thing I had to change was remove 3. in your answer and add a constraint that aligns viewC with the contentView's center Y. The views then become vertically centered in the cell. –  Michael Gaylord Sep 16 at 10:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.