24

I have an iOS view with autolayout enabled and have a UIToolbar with a UISearchBar and UISegmentControl contained with the toolbar. I want the UISearchBar to have a flexible width so I need to add a constraint to force this, but from what I can tell you cannot add constraints to items in a UIToolbar in Interface Builder. The options are all disabled.

Before AutoLayout I would accomplish this with autoresizingmasks.

Are constraints not allowed within UIToolbars/UINavigationBars?

How else can this be accomplished when using autolayout?

Dilip
  • 8,873
  • 4
  • 40
  • 56
outerstorm
  • 642
  • 1
  • 7
  • 16
  • I've done some stuff like this before, though I basically just wait for the size of the view to change and then update the frame of the target view accordingly. That's always an option if it turns out there is not a way to do it automagically. – Brian Feb 20 '13 at 15:25
  • could you post an image? – Vaibhav Saran Mar 20 '13 at 07:31
  • I would, but I ended up abandoning AutoLayout and going back to using autoresizingmasks. It works great using that model. – outerstorm Mar 21 '13 at 12:13
  • @Brian How do you recommend observing the size of the view changing? – devios1 Apr 28 '15 at 18:02
  • 1
    @devios not sure of your use-case, but layoutSubViews is likely what you want. That will be called when the orientation is changed, etc. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html – Brian Apr 29 '15 at 14:29

3 Answers3

26

Autolayout constraints only work with UIViews and their subclasses.

While UIToolbar allows some UIView based items (such as UISearchBar and UISegmentedControl) they may have to coexist with UIBarButtonItems which do not inherit from UIView.

Until autolayout can work with UIBarButtonItems, do as you have done.

Your alternative is to roll your own toolbar with widgets based only on UIViews.

Vineet Singh
  • 4,775
  • 1
  • 28
  • 39
snorock
  • 408
  • 5
  • 8
  • 4
    Any idea if Apple are working into resolving this ? It bugs me that inconsistency is broken if I have to use AL and the old approach in different places... – Petar Nov 26 '14 at 14:48
9

This can also be done right from a storyboard.

Just drag and drop items in the toolbar, and turn some of them into flexible or fixed space to get the desired effect. See the two examples below.

Evenly spaced

Centered

NB: this is a copy of my answer to Aligning UIToolBar items, I stumbbled upon both questions while looking for such a solution

Community
  • 1
  • 1
Arnaud
  • 15,630
  • 9
  • 57
  • 78
7

You can do this in code, at least; I'm the type to forsake Interface Builder and go it in code anyway. IB seems to get in my way more often than not when it comes to adding or tweaking constraints. Here's what I've done in my custom UIToolbar subclass's -initWithFrame: method.

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self addSubview:self.label];

        [self addConstraint:[NSLayoutConstraint
                             constraintWithItem:self.label
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                             toItem:self
                             attribute:NSLayoutAttributeCenterX
                             multiplier:1 constant:0]];
        [self addConstraint:[NSLayoutConstraint
                             constraintWithItem:self.label
                             attribute:NSLayoutAttributeCenterY
                             relatedBy:NSLayoutRelationEqual
                             toItem:self
                             attribute:NSLayoutAttributeCenterY
                             multiplier:1 constant:0]];
    }
    return self;
}

And since I like to lazy load as much as possible, here's my self.label instance variable (called when [self addSubview:self.label] gets messaged above).

- (UILabel *)label {
    if (_label) return _label;
    _label = [UILabel new];
    _label.translatesAutoresizingMaskIntoConstraints = NO;
    _label.textAlignment = NSTextAlignmentCenter;
    return _label;
}

Seems to work for me. I'm not adding any UIBarButtonItems, though, so your mileage my vary.

Ben Kreeger
  • 6,325
  • 2
  • 36
  • 53
  • If you are trying to reposition an existing toolbar using constraints, you'll find the NSLayoutAttributeCenterX constraint to be very useful. – russes Aug 09 '13 at 14:08