开发者

How do I resize a UIButton to fit the text without it going wider than the screen?

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 the button as needed.

I've set line breaks to Word Wrap and tried sizeT开发者_C百科oFit but that only makes the button go wider, not vertical.


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):

  1. Click on the UIButton
  2. in the Size inspector drag content hugging to 1 (both horizontal and vertical)
  3. drag compression resistance to 1000 (for both)
  4. under the UIButton's constraints click on Width and change priority to 250
  5. Do the same for Height
  6. You can use the UIButton's inset to control padding for left/right/top/bottom


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.


I'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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜