2

I'm new in auto layout so reading a bit questions here in stack I'm trying to align my 5 UIButtons at the bottom of the cell to have equal space (of 7 points for example), I tried using code and it doesn't work.

My question is - how can I do it using Interface Builder?

UIButton *button1 = self.btnFavorite, *button2 = self.btnCalendar, *button3 = self.btnEmail,
             *button4 = self.btnMessage, *button5 = self.btnCall;
    NSMutableArray *constraintsForButtons = [[NSMutableArray alloc] init];

    float unusedHorizontalSpace = self.bounds.size.width - button1.intrinsicContentSize.width - button2.intrinsicContentSize.width - button3.intrinsicContentSize.width - button4.intrinsicContentSize.width - button5.intrinsicContentSize.width;
    NSNumber *spaceBetweenEachButton =  [NSNumber numberWithFloat: unusedHorizontalSpace / 5 ] ;

    [constraintsForButtons addObjectsFromArray:[NSLayoutConstraint
                                                constraintsWithVisualFormat: @"H:|-(space)-[button1]-(space)-[button2]-(space)-[button3]-(space)-[button4]-(space)-[button5]-(space)-|"
                                                options:NSLayoutFormatAlignAllCenterY
                                                metrics:@{@"space":spaceBetweenEachButton}

                                                views:NSDictionaryOfVariableBindings(button1,button2, button3,button4, button5)]];

    [constraintsForButtons addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat: @"V:|[button1]"
                                                                                        options: 0
                                                                                        metrics: nil
                                                                                          views: NSDictionaryOfVariableBindings(button1) ] ] ;
    [self addConstraints:constraintsForButtons] ;

Error:

2014-10-09 03:04:07.501 Human Response[2972:781746] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x1568f260 H:[UIButton:0x1568f100(20)]>",
    "<NSLayoutConstraint:0x15690b90 H:[UIButton:0x15690fc0(20)]>",
    "<NSLayoutConstraint:0x156921c0 H:[UIButton:0x15692d00(20)]>",
    "<NSLayoutConstraint:0x1568d4f0 H:[UIButton:0x1568d8e0(20)]>",
    "<NSLayoutConstraint:0x1558b4c0 H:[UIButton:0x15598410(20)]>",
    "<NSLayoutConstraint:0x155993d0 H:|-(-60)-[UIButton:0x15598410]   (Names: '|':UITableViewCellContentView:0x15673e40 )>",
    "<NSLayoutConstraint:0x15599550 H:[UIButton:0x15598410]-(-60)-[UIButton:0x1568d8e0]>",
    "<NSLayoutConstraint:0x155996e0 H:[UIButton:0x1568d8e0]-(-60)-[UIButton:0x15692d00]>",
    "<NSLayoutConstraint:0x15599740 H:[UIButton:0x15692d00]-(-60)-[UIButton:0x15690fc0]>",
    "<NSLayoutConstraint:0x155997a0 H:[UIButton:0x15690fc0]-(-60)-[UIButton:0x1568f100]>",
    "<NSLayoutConstraint:0x15599800 H:[UIButton:0x1568f100]-(-60)-|   (Names: '|':UITableViewCellContentView:0x15673e40 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1558b4c0 H:[UIButton:0x15598410(20)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-10-09 03:04:07.633 Human Response[2972:781746] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x155a2de0 H:[UIButton:0x155a2fc0(20)]>",
    "<NSLayoutConstraint:0x155a33d0 H:[UIButton:0x155a32d0(20)]>",
    "<NSLayoutConstraint:0x155a3750 H:[UIButton:0x155a3620(20)]>",
    "<NSLayoutConstraint:0x155a1bc0 H:[UIButton:0x155a1a60(20)]>",
    "<NSLayoutConstraint:0x155a3df0 H:[UIButton:0x155a3cc0(20)]>",
    "<NSLayoutConstraint:0x156a4770 H:|-(-60)-[UIButton:0x155a3cc0]   (Names: '|':UITableViewCellContentView:0x155a2150 )>",
    "<NSLayoutConstraint:0x156a47b0 H:[UIButton:0x155a3cc0]-(-60)-[UIButton:0x155a1a60]>",
    "<NSLayoutConstraint:0x156a4840 H:[UIButton:0x155a1a60]-(-60)-[UIButton:0x155a3620]>",
    "<NSLayoutConstraint:0x156a48c0 H:[UIButton:0x155a3620]-(-60)-[UIButton:0x155a32d0]>",
    "<NSLayoutConstraint:0x156a4920 H:[UIButton:0x155a32d0]-(-60)-[UIButton:0x155a2fc0]>",
    "<NSLayoutConstraint:0x1569fa50 H:[UIButton:0x155a2fc0]-(-60)-|   (Names: '|':UITableViewCellContentView:0x155a2150 )>"
)

enter image description here

Idan Moshe
  • 1,675
  • 4
  • 28
  • 65

2 Answers2

1

The only way I've found to do this with IB is to create spacer views between the views that you want to distribute evenly, with all of their edges connected to the neighboring edges of the views that you want to distribute evenly. You give them variable width/height, and then add constraints that say that all of the spacer views must have the same width/height.

It's very tedious to set up, but it does work.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
1

As Duncan C said in his answer, using spacer views is the way to go. In case you want to do it in code, here is some code I've used in the past to create buttons that are equally spaced.

-(void)viewDidLoad {
    [super viewDidLoad];

    NSMutableDictionary *viewsDict = [NSMutableDictionary dictionary];
    NSArray *titles = @[@"Short",@"Longer",@"Short",@"The Longest"];
    for (int i=1; i<5; i++) {
        UIButton *b = [UIButton buttonWithType:UIButtonTypeSystem];
        [b setTitle:titles[i-1] forState:UIControlStateNormal];
        [b setTranslatesAutoresizingMaskIntoConstraints:NO];
        [viewsDict setObject:b forKey:[NSString stringWithFormat:@"b%d",i]];
    }

    for (int i=1; i<6; i++) {
        UILabel *l = [[UILabel alloc ]init]; // these labels are the spacers
        [l setTranslatesAutoresizingMaskIntoConstraints:NO];
        [viewsDict setObject:l forKey:[NSString stringWithFormat:@"l%d",i]];
    }

    for (id obj in viewsDict.allKeys)
        [self.view addSubview:viewsDict[obj]];

    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[l1][b1][l2(==l1)][b2][l3(==l1)][b3][l4(==l1)][b4][l5(==l1)]|"
                                                                   options:NSLayoutFormatAlignAllBaseline
                                                                   metrics:nil
                                                                     views:viewsDict];

    NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[b1]-|"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:viewsDict];


    [self.view addConstraints:constraints];
    [self.view addConstraints:constraints2];
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218