Adjust UILabel height depending on the text

2018-12-31 06:20发布

Consider I have the following text in a UILabel (a long line of dynamic text):

Since the alien army vastly outnumbers the team, players must use the post-apocalyptic world to their advantage, such as seeking cover behind dumpsters, pillars, cars, rubble, and other objects.

I want to resize the UILabel's height so that the text can fit in. I'm using following properties of UILabel to make the text within to wrap.

myUILabel.lineBreakMode = UILineBreakModeWordWrap;
myUILabel.numberOfLines = 0;

Please let me know if I'm not heading in the right direction. Thanks.

30条回答
泪湿衣
2楼-- · 2018-12-31 06:47

My approach to compute the dynamic height of UILabel.

    let width = ... //< width of this label 
    let text = ... //< display content

    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.preferredMaxLayoutWidth = width

    // Font of this label.
    //label.font = UIFont.systemFont(ofSize: 17.0)
    // Compute intrinsicContentSize based on font, and preferredMaxLayoutWidth
    label.invalidateIntrinsicContentSize() 
    // Destination height
    let height = label.intrinsicContentSize.height

Wrap to function:

func computeHeight(text: String, width: CGFloat) -> CGFloat {
    // A dummy label in order to compute dynamic height.
    let label = UILabel()

    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.font = UIFont.systemFont(ofSize: 17.0)

    label.preferredMaxLayoutWidth = width
    label.text = text
    label.invalidateIntrinsicContentSize()

    let height = label.intrinsicContentSize.height
    return height
}
查看更多
美炸的是我
3楼-- · 2018-12-31 06:48

Finally, it worked. Thank you guys.

I was not getting it to work because i was trying to resize the label in heightForRowAtIndexPath method:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

and (yeah silly me), i was resizing the label to default in cellForRowAtIndexPath method - i was overlooking the code i had written earlier:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
查看更多
冷夜・残月
4楼-- · 2018-12-31 06:49

You may use it as a method, as well. @Pyjamasam is very much true so i am just making its method. It may be helpfull for some one else

-(CGRect)setDynamicHeightForLabel:(UILabel*)_lbl andMaxWidth:(float)_width{
    CGSize maximumLabelSize = CGSizeMake(_width, FLT_MAX);

    CGSize expectedLabelSize = [_lbl.text sizeWithFont:_lbl.font constrainedToSize:maximumLabelSize lineBreakMode:_lbl.lineBreakMode];

    //adjust the label the the new height.
    CGRect newFrame = _lbl.frame;
    newFrame.size.height = expectedLabelSize.height;
    return newFrame;
}

and just set it like this

label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];
查看更多
美炸的是我
5楼-- · 2018-12-31 06:50

UILabel extension based on this answer for Swift 4 and above

extension UILabel {

    func retrieveTextHeight () -> CGFloat {
        let attributedText = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:self.font])

        let rect = attributedText.boundingRect(with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)

        return ceil(rect.size.height)
    }

}

Can be used like:

self.labelHeightConstraint.constant = self.label.retrieveTextHeight()
查看更多
只若初见
6楼-- · 2018-12-31 06:51

Swift 2:

    yourLabel.text = "your very long text"
    yourLabel.numberOfLines = 0
    yourLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
    yourLabel.frame.size.width = 200
    yourLabel.frame.size.height = CGFloat(MAXFLOAT)
    yourLabel.sizeToFit()

The interesting lines are sizeToFit() in conjunction with setting a frame.size.height to the max float, this will give room for long text, but sizeToFit() will force it to only use the necessary, but ALWAYS call it after setting the .frame.size.height .

I recommend setting a .backgroundColor for debug purposes, this way you can see the frame being rendered for each case.

查看更多
骚的不知所云
7楼-- · 2018-12-31 06:55

Since sizeWithFont is deprecated I use this one instead.

this one get label specific attributes.

-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text{

    NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:label.font}];
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){label.frame.size.width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];

    return ceil(rect.size.height);
}
查看更多
登录 后发表回答