I have a UIButton that I want to resize to fit whatever text is inside it. It has a set width of 280, but the text should wrap to the next line(s) and extend the height of
Make sure you set the text on your button this way:
[myButton setTitle:@"my title" forState:UIControlStateNormal];
... and [myButton sizeToFit]
should work like a charm.
[button sizeToFit]
didn't work for me, but I've found a way using IB alone (xcode 4.5):
UIButton
content hugging
to 1 (both horizontal and vertical)compression resistance
to 1000 (for both)constraints
click on Width
and change priority
to 250UIButton
's inset
to control padding for left/right/top/bottomI've been facing a similar problem, had limited width for my buttons and wanted them to grow vertically, depending on the amount of text I'd give them. I ended up with a simple solution, based on what I've learnt in the Apple docs (https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/ImplementingView/ImplementingView.html)
I've subclassed UIButton
and overridden two functions:
- (void)setBounds:(CGRect)bounds {
if (!CGRectEqualToRect(bounds, self.bounds)) {
[self invalidateIntrinsicContentSize];
}
[super setBounds:bounds];
}
- (CGSize)intrinsicContentSize {
//
CGSize size;
self.titleLabel.frame = CGRectMake(self.titleLabel.frame.origin.x,
self.titleLabel.frame.origin.y,
self.frame.size.width - self.contentEdgeInsets.left - self.contentEdgeInsets.right - self.titleEdgeInsets.left - self.titleEdgeInsets.right,
0);
size = [self.titleLabel sizeThatFits:self.titleLabel.frame.size];
size = CGSizeMake(size.width, size.height + 20);
return size;
}
What basically happens here is that the button invalidates its intrinsic size (only when the bounds set are actually new -- this is to prevent an endless loop), and when the system asks for the intrinsic content size, I recalculate that based on the width of the button. The extra 20px height is for padding. I've tried many other ways but since my layout is all based on AutoLayout, I wanted something that I don't have to update whenever the device rotates or so. This simply works.
Good luck! Z.
I managed to get it working in a category of UIButton:
@interface UIButton (ExpandsVertically)
- (CGSize)sizeThatFits:(CGSize)size;
@end
@implementation UIButton (Expandable)
- (CGSize)sizeThatFits:(CGSize)size {
// for the width, I subtract 24 for the border
// for the height, I use a large value that will be reduced when the size is returned from sizeWithFont
CGSize tempSize = CGSizeMake(size.width - 24, 1000);
CGSize stringSize = [self.titleLabel.text
sizeWithFont:self.titleLabel.font
constrainedToSize:tempSize
lineBreakMode:UILineBreakModeWordWrap];
return CGSizeMake(size.width - 24, stringSize.height);
}
@end
If anyone uses this make sure to set:
myButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
You may want to look at the UIKit Additions to NSString documentation which includes methods for font measurement constrained to a specific width or box size.
When you set the button's title, you could measure the string using the sizeWithFont:forWidth:lineBreakMode: method, for example, and update your button's frame based on the size returned (possibly allowing for some padding around the edges).
Sorry I don't have a specific example for you.