UIButton that resizes to fit its titleLabel UIButton that resizes to fit its titleLabel ios ios

UIButton that resizes to fit its titleLabel


Swift 4.x version of Kubba's answer:

Need to Update Line Break as Clip/WordWrap/ in Interface builder to corresponding buttons.

class ResizableButton: UIButton {    override var intrinsicContentSize: CGSize {       let labelSize = titleLabel?.sizeThatFits(CGSize(width: frame.width, height: .greatestFiniteMagnitude)) ?? .zero       let desiredButtonSize = CGSize(width: labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)       return desiredButtonSize    }}


I've gotten this to work, but you have to use a custom button, not a system type. Give the button both width and height constraints, and make an IBOutlet to the height constraint (heightCon in my code) so you can adjust it in code.

- (void)viewDidLoad {    [super viewDidLoad];    self.button.titleLabel.numberOfLines = 0;    self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;    [self.button setTitle:@"A real real real real real real real real long long name." forState:UIControlStateNormal];    [self.button addTarget:self action:@selector(doStuff:) forControlEvents:UIControlEventTouchUpInside];    self.button.backgroundColor = [UIColor redColor];    self.button.titleLabel.backgroundColor = [UIColor blueColor];    [self.button layoutIfNeeded]; // need this to update the button's titleLabel's size    self.heightCon.constant = self.button.titleLabel.frame.size.height;}

After Edit:

I found that you can also do this more simply, and with a system button if you make a subclass, and use this code,

@implementation RDButton-(CGSize)intrinsicContentSize {    return CGSizeMake(self.frame.size.width, self.titleLabel.frame.size.height);}

The overridden intrinsicContentSize method is called when you set the title. You shouldn't set a height constraint in this case.


Got same issue. It happens only if UIButton's titleLabel has more than one line. Is it a bug in UIKit?

My Swift solution:

class ResizableButton: UIButton {        override var intrinsicContentSize: CGSize {        let labelSize = titleLabel?.sizeThatFits(CGSize(width: frame.size.width, height: CGFloat.greatestFiniteMagnitude)) ?? .zero        let desiredButtonSize = CGSize(width: labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)        return desiredButtonSize    }}