简体   繁体   中英

How to get a button to grow vertically using Auto Layout in iOS7?

Using IB and Auto Layout I would like to have a button that grows in size vertically when the title is long.

I've added top, leading and trailing constraint to the button and a Line break of Word wrap. Then I assign a long title in viewDidLoad. But the resulting button doesn't fit the content. What am I missing here?

IB

仿真器

纽扣

约束条件

Trying to overcome the lack of automated update of the height:

CGFloat width = 280;
NSAttributedString *attributedText =
[[NSAttributedString alloc]
 initWithString:self.button.titleLabel.text
 attributes:@
 {NSFontAttributeName: self.button.titleLabel.font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
CGSize size = rect.size;
CGRect buttonRect = self.button.frame;
buttonRect.size.height = size.height;
[self.button setFrame: buttonRect];

But the frame of the button is not being updated.....

With the excellent solution provided by rdelmar below I got the following result:

在此处输入图片说明

If you want the title over the image (not beside) you need to use backgroundImage:forState:. As far as I can tell from experimenting with this, you can't get the image to expand with the title in an automatic way. If you have no image, then those constraints work to make the title expand vertically.

After Edit: I never found any good automatic way to do this, but you can do it by calculating the height of the string, and adjusting the height of the button accordingly. I found the best way to do this was to give the button both a width and height constraint in IB -- this will cause your background image to stretch or shrink to fit that frame. I made a UIButton subclass (changed the class of the the button in IB), and put this code in it:

@interface RDButton ()
@property (strong,nonatomic) NSLayoutConstraint *hCon;
@property (strong,nonatomic) NSLayoutConstraint *wCon;
@property (nonatomic) CGFloat startingHeight;
@end

@implementation RDButton

-(id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        for (NSLayoutConstraint *con in self.constraints) {
            if (con.firstAttribute == NSLayoutAttributeHeight) {
                self.hCon = con;
                self.startingHeight = con.constant;
            }else if (con.firstAttribute == NSLayoutAttributeWidth){
                self.wCon = con;
            }
        }
    }
    self.titleLabel.numberOfLines = 0;
    self.titleLabel.textAlignment = NSTextAlignmentCenter;
    return self;
}

-(void)setTitle:(NSString *)title forState:(UIControlState)state {
    [super setTitle:title forState:state];
    NSStringDrawingContext *ctx = [NSStringDrawingContext new];
    CGSize s = [title boundingRectWithSize:CGSizeMake(self.wCon.constant, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.titleLabel.font} context:ctx].size;
    self.hCon.constant = fmax (s.height, self.startingHeight - 5) + 5; // the +5 gives about the same padding as the original button.
}

In the view controller where I'm setting the new title, I have this:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.button setTitle:@"A long long long Title" forState:UIControlStateNormal];
    UIImage *img = [UIImage imageNamed:@"pic.jpg"];
    [self.button setBackgroundImage:img forState:UIControlStateNormal];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM