Multiline UIButton and autolayout

autolayout, ios, uibutton

Solution

I had the same problem where I wanted my button to grow along with its title. I had to sublcass the `UIButton` and its `intrinsicContentSize` so that it returns the intrinsic size of the label.

- (CGSize)intrinsicContentSize
{
    return self.titleLabel.intrinsicContentSize;
}

Since the `UILabel` is multiline, its `intrinsicContentSize` is unknown and you have to set its `preferredMaxLayoutWidth` See objc.io article about that

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.frame.size.width;
    [super layoutSubviews];
}

The rest of the layout should work. If you set your both button having equal heights, the other one will grow to. The complete button looks like this

@implementation TAButton

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        self.titleLabel.numberOfLines = 0;
        self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    }
    return self;
}

- (CGSize)intrinsicContentSize
{
    return self.titleLabel.intrinsicContentSize;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.frame.size.width;
    [super layoutSubviews];
}

@end

Problem

I have created a view controller that looks like this: I want the two top buttons to always have 20 points between themselves and the left/right edges of the whole view. They should always have the same width too. I have created the constraints for all of this and it works exactly how I want it to. The problem is the vertical constraints. The buttons should always be 20 points beneath the top edge. They should have the same height. However, autolayout doesn't respect that the left label needs two lines to fit all its text, so the result looks like this: I want it to look like in the first picture. I can't add constant height constraints to the buttons because when the app runs on iPad, only one line is needed and it would be wasteful to have extra space then. In `viewDidLoad` I tried this: ``` - (void)viewDidLoad { [super viewDidLoad]; self.leftButton.titleLabel.preferredMaxLayoutWidth = (self.view.frame.size.width - 20.0 * 3) / 2.0; self.rightButton.titleLabel.preferredMaxLayoutWidth = (self.view.frame.size.width - 20.0 * 3) / 2.0; } ``` But that did not change anyhting at all. The question: How do I make autolayout respect that the left button needs two lines?

Original source