Pergunta

I'm trying to get a hang of NSLayoutConstraints visual format and I am having a little trouble.

What I want is basically a simple UIView with two labels, one on the left, and one on the right, with heights equal to the height of the container, and the widths equal to 1/2 of the container width. The origin of the right label is aligned to the trailing of the left label.

| LEFT LABEL - RIGHT LABEL|

Anyway, here is my attempt:

self.leftLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.rightLabel.translatesAutoresizingMaskIntoConstraints = NO;

NSDictionary *views     = @{ @"leftLabel"       :   self.leftLabel,
                             @"rightLabel"      :   self.rightLabel };

NSDictionary *metrics   = @{ @"width"           :   @(CGRectGetWidth(self.frame) / 2) };

NSArray *constraints;
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[leftLabel]-|" options:0 metrics:metrics views:views];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[rightLabel]-|" options:0 metrics:metrics views:views];
[self addConstraints:constraints];
constraints  = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[leftLabel(width)]" options:0 metrics:metrics views:views];
[self addConstraints:constraints];
constraints  = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-width-[rightLabel(width)]" options:0 metrics:metrics views:views];
[self addConstraints:constraints];

[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];

Unfortunately, the width of each label remains 0 after this executes. Any suggestions?

UPDATE

Here's the whole class:

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        self.leftLabel      = [UILabel new];
        self.rightLabel     = [UILabel new];
        self.loadingView    = [[DDLoadingView alloc] init];

        self.rightLabel.backgroundColor = [UIColor redColor];
        self.leftLabel.backgroundColor = [UIColor redColor];
        self.backgroundColor = [UIColor blackColor];

        [self addSubview:self.leftLabel];
        [self addSubview:self.rightLabel];

        [self configureLayout];
    }

    return self;
}

- (void)configureLayout
{
    self.leftLabel.translatesAutoresizingMaskIntoConstraints = NO;
    self.rightLabel.translatesAutoresizingMaskIntoConstraints = NO;

    NSDictionary *views     = @{ @"leftLabel"       :   self.leftLabel,
                                 @"rightLabel"      :   self.rightLabel,
                                 @"loadingView"     :   self.loadingView  };

    NSDictionary *metrics   = @{ @"width"           :   @(CGRectGetWidth(self.frame) / 2) };

    NSArray *constraints;
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[leftLabel]-|" options:0 metrics:metrics views:views];
    [self addConstraints:constraints];
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[rightLabel]-|" options:0 metrics:metrics views:views];
    [self addConstraints:constraints];
    constraints  = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[leftLabel]-[rightLabel(==leftLabel)]-|" options:0 metrics:metrics views:views];
    [self addConstraints:constraints];

    [self setNeedsUpdateConstraints];
    [self updateConstraintsIfNeeded];
}
Foi útil?

Solução

You need to set the constraints to use the widths of the other views:

NSArray *constraints;
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[leftLabel]-|" options:0 metrics:metrics views:views];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[rightLabel]-|" options:0 metrics:metrics views:views];
[self addConstraints:constraints];
constraints  = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[leftLabel]-[rightLabel(==leftLabel)]-|" options:0 metrics:metrics views:views];
[self addConstraints:constraints];

The last constraint is saying make those two views the same width while pinning them to the left/right egdes of the superview. See the Equal Widths section of the docs

As discussed in the comments, you need to also make sure that the frame of the superview can accommodate the views themselves. |-[ will use the default insets of 20, using |-2- will give insets of 2. If the intrinsic height of the labels is more than the views height minus these insets your view isn't going to show. So you either need to reduce the insets or increase the height of the container.

If you want more information on AutoLayout I recommend the following series of blog posts by @jrturton - see the top of the article for other posts in the series. He's also got a great category on UIView to make adding constraints easier, I use this daily!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top