8

Is it possible to equally distribute left and right space for b in @"|-[a(5)]-[b(8)]-[c(5)]-|" using visual format strings?

flohei
  • 5,248
  • 10
  • 36
  • 61
  • VERY GOOD SO article related to this question [here](http://stackoverflow.com/questions/13075415/evenly-space-multiple-views-within-a-container-view/25898949#25898949) – Martin Berger Jul 07 '15 at 20:35

2 Answers2

15

No.

However, you can do it with visual format and a manual constraint creation. Change your VFL string to:

@"|-[a(5)]->=0-[b(8)]->=0-[c(5)]-|"

This says that you're not too concerned about the actual size of the spaces between a and b, and b and c.

Now, create a constraint pinning the center of b to the center of the superview using constraintWithItem:... (I'm typing this on a phone so forgive me for not spelling out the whole method).

This, coupled with your flexible spacing, will give even spaces to the left and right of b.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • How exactly did you “pin the center of b to the center of the superview”, @flohei? And isn’t it possible to use the visual format for that as well or must one use `constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:`? – freya May 09 '14 at 14:11
15

Apple's Auto Layout Guide suggests using "spacer views". Here's the solution for laying out your three views with equal spacing horizontally:

// create views dictionary
NSMutableDictionary *viewsDictionary = [NSMutableDictionary dictionary];
[viewsDictionary addEntriesFromDictionary:NSDictionaryOfVariableBindings(viewA, viewB, viewC)];

// create 4 spacer views
for (int i = 0; i < 4; i++) {
    UIView *spacerView = [[UIView alloc] init];
    spacerView.hidden = YES;
    [self addSubview:spacerView];
    [viewsDictionary setObject:spacerView
                        forKey:[NSString stringWithFormat:@"spacer%d", i + 1]];
}

// disable translatesAutoresizingMaskIntoConstraints in views for auto layout
[viewsDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) 
{
    [obj setTranslatesAutoresizingMaskIntoConstraints:NO];
}];

// add constraints
[superview addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:
  @"|[spacer1(>=0)][viewA][spacer2(==spacer1)][viewB][spacer3(==spacer1)][viewC][spacer4(==spacer1)]|"
                                         options:kNilOptions
                                         metrics:nil
                                           views:viewsDictionary]];

Note that spacer1's width is set to be more than 0. Subsequent spacer views are set to have equal widths with spacer1.

Benjamin Cheah
  • 1,401
  • 17
  • 23
  • Is there any reason you didn’t simply write `NSDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB, viewC);`? – freya May 04 '14 at 05:37
  • I've edited my answer to use multiple arguments in NSDictionaryOfVariableBindings. I'm using a mutable dictionary so that I can add my spacer views to it dynamically. – Benjamin Cheah May 09 '14 at 03:56
  • Oh, right. ^___^ `NSMutableDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB, viewC).mutableCopy;` then. – freya May 09 '14 at 13:58