Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton that resizes to fit its titleLabel

I have a UIButton that I add to my view controller's view in a storyboard. I add centering constraints to position it and leading space constraints to limit its width. In code I add:

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.backgroundColor = [UIColor redColor]; self.button.titleLabel.backgroundColor = [UIColor blueColor]; 

The result is shown below:

enter image description here

I want the button to size to its content. How can I do this?

I've tried

[self.button sizeToFit]; 

and I've tried setting the content hugging and compression resistance autolayout constraints priorities to required.

I've also tried explicitly setting the contentEdgeInsets and titleEdgeInsets to UIEdgeInsetsZero and calling invalidateIntrinsicContentSize.

I've also noticed that if I place newline characters in the title string, the button does seem to resize to fit its content.

I'm running on Xcode 6 and iOS 8 on the iPhone 6 Simulator.

like image 273
Darren Avatar asked Dec 02 '14 21:12

Darren


2 Answers

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     } } 
like image 136
A. Buksha Avatar answered Oct 02 '22 17:10

A. Buksha


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.

like image 20
rdelmar Avatar answered Oct 02 '22 18:10

rdelmar