首页 文章

根据文字调整UILabel高度

提问于
浏览
297

考虑我在 UILabel (动态文本的长行)中有以下文本:

由于外星军队的数量远远超过团队,因此玩家必须利用后世界末日的世界,例如在垃圾箱,支柱,汽车,瓦砾和其他物体后面寻找掩护 .

我想调整 UILabel's 高度,以便文本可以适应 . 我正在使用 UILabel 的以下属性来使文本内部包装 .

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

如果我没有朝着正确的方向前进,请告诉我 . 谢谢 .

30 回答

  • 0

    sizeWithFont constrainedToSize:lineBreakMode: 是要使用的方法 . 以下是如何使用它的示例:

    //Calculate the expected size based on the font and linebreak mode of your label
    // FLT_MAX here simply means no constraint in height
    CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
    
    CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];   
    
    //adjust the label the the new height.
    CGRect newFrame = yourLabel.frame;
    newFrame.size.height = expectedLabelSize.height;
    yourLabel.frame = newFrame;
    
  • 41

    你正朝着正确的方向前进 . 你需要做的就是:

    myUILabel.numberOfLines = 0;
    myUILabel.text = @"Enter large amount of text here";
    [myUILabel sizeToFit];
    
  • 1

    克里斯的答案是错误的 .

    newFrame.size.height = maximumLabelSize.height;
    

    应该

    newFrame.size.height = expectedLabelSize.height;
    

    除此之外,这是正确的解决方案 .

  • 15

    在iOS 6中,Apple为 UILabel 添加了一个属性,极大地简化了标签的动态垂直大小调整: preferredMaxLayoutWidth .

    将此属性与lineBreakMode = NSLineBreakByWordWrapping和sizeToFit方法结合使用,可以轻松地将UILabel实例的大小调整为适应整个文本的高度 .

    来自iOS文档的引用:

    preferredMaxLayoutWidth多行标签的首选最大宽度(以磅为单位) . 讨论当应用布局约束时,此属性会影响标签的大小 . 在布局期间,如果文本超出此属性指定的宽度,则附加文本将流向一个或多个新行,从而增加标签的高度 .

    一个样品:

    ...
    UILabel *status = [[UILabel alloc] init];
    status.lineBreakMode = NSLineBreakByWordWrapping;
    status.numberOfLines = 5; // limits to 5 lines; use 0 for unlimited.
    
    [self addSubview:status]; // self here is the parent view
    
    status.preferredMaxLayoutWidth = self.frame.size.width; // assumes the parent view has its frame already set.
    
    status.text = @"Some quite lengthy message may go here…";
    [status sizeToFit];
    [status setNeedsDisplay];
    ...
    
  • 235

    而是以编程方式执行此操作,您可以在设计时在Storyboard / XIB中执行此操作 .

    • 在属性检查器中将UIlabel的 number of lines 属性设置为 0 .

    • 然后根据要求设置宽度约束/(或)前导和尾随约束 .

    • 然后 set height constraintminimum value . 最后选择您添加的高度约束,并在尺寸检查器中选择属性检查器旁边的高度约束, change 高度约束的 relation 来自 equal to - greater than .

  • 1

    无需添加单行代码即可完美检查此工作 . (使用Autolayout)

    我根据你的要求为你做了一个 demo . 从以下链接下载,

    Autoresize UIView and UILabel

    Step by Step Guide :-

    Step 1 :- 将约束设置为UIView

    1)领先2)Top 3)尾随(来自主视图)

    enter image description here

    Step 2 :- 将约束设置为标签1

    1)领先2)前3)尾随(从它的超级视图)

    enter image description here

    Step 3 :- 将约束设置为标签2

    1)领先2)尾随(从它的超级视图)

    enter image description here

    Step 4 :- Most tricky 从UIView向UILabel提供帮助 .

    enter image description here

    Step 5 :- (可选)将约束设置为UIButton

    1)领先2)底部3)尾随4)固定高度(来自主视图)

    enter image description here

    Output :-

    enter image description here

    Note :- 确保在Label属性中设置了Number of lines = 0 .

    enter image description here

    我希望这个信息足以理解Autoresize UIView根据UILabel的高度和Autoresize UILabel根据文字 .

  • 3

    谢谢大家的帮助,这是我尝试的代码,这对我有用

    UILabel *instructions = [[UILabel alloc]initWithFrame:CGRectMake(10, 225, 300, 180)];
       NSString *text = @"First take clear picture and then try to zoom in to fit the ";
       instructions.text = text;
       instructions.textAlignment = UITextAlignmentCenter;
       instructions.lineBreakMode = NSLineBreakByWordWrapping;
       [instructions setTextColor:[UIColor grayColor]];
    
       CGSize expectedLabelSize = [text sizeWithFont:instructions.font 
                                    constrainedToSize:instructions.frame.size
                                        lineBreakMode:UILineBreakModeWordWrap];
    
        CGRect newFrame = instructions.frame;
        newFrame.size.height = expectedLabelSize.height;
        instructions.frame = newFrame;
        instructions.numberOfLines = 0;
        [instructions sizeToFit];
        [self addSubview:instructions];
    
  • 2

    Solution to iOS7 prior and iOS7 above

    //
    //  UILabel+DynamicHeight.m
    //  For StackOverFlow
    //
    //  Created by Vijay on 24/02/14.
    //  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    
    #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    
    #define iOS7_0 @"7.0"
    
    @interface UILabel (DynamicHeight)
    
    /*====================================================================*/
    
    /* Calculate the size,bounds,frame of the Multi line Label */
    
    /*====================================================================*/
    /**
     *  Returns the size of the Label
     *
     *  @param aLabel To be used to calculte the height
     *
     *  @return size of the Label
     */
    
    -(CGSize)sizeOfMultiLineLabel;
    
    @end
    
    
    //
    //  UILabel+DynamicHeight.m
    //  For StackOverFlow
    //
    //  Created by Vijay on 24/02/14.
    //  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
    //
    
    #import "UILabel+DynamicHeight.h"
    
    @implementation UILabel (DynamicHeight)
    /*====================================================================*/
    
    /* Calculate the size,bounds,frame of the Multi line Label */
    
    /*====================================================================*/
    /**
     *  Returns the size of the Label
     *
     *  @param aLabel To be used to calculte the height
     *
     *  @return size of the Label
     */
    -(CGSize)sizeOfMultiLineLabel{
    
        NSAssert(self, @"UILabel was nil");
    
        //Label text
        NSString *aLabelTextString = [self text];
    
        //Label font
        UIFont *aLabelFont = [self font];
    
        //Width of the Label
        CGFloat aLabelSizeWidth = self.frame.size.width;
    
    
        if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
            //version < 7.0
    
            return [aLabelTextString sizeWithFont:aLabelFont
                                constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                    lineBreakMode:NSLineBreakByWordWrapping];
        }
        else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
            //version >= 7.0
    
            //Return the calculated size of the Label
            return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:@{
                                                            NSFontAttributeName : aLabelFont
                                                            }
                                                  context:nil].size;
    
        }
    
        return [self bounds].size;
    
    }
    
    @end
    
  • 1

    由于不推荐使用sizeWithFont,我使用这个 .

    这个获得标签特定的属性 .

    -(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);
    }
    
  • 399

    这是一个类别版本:

    UILabel+AutoSize.h #import

    @interface UILabel (AutoSize)
    
    - (void) autosizeForWidth: (int) width;
    
    @end
    

    UILabel+AutoSize.m

    #import "UILabel+AutoSize.h"
    
    @implementation UILabel (AutoSize)
    
    - (void) autosizeForWidth: (int) width {
        self.lineBreakMode = UILineBreakModeWordWrap;
        self.numberOfLines = 0;
        CGSize maximumLabelSize = CGSizeMake(width, FLT_MAX);
        CGSize expectedLabelSize = [self.text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
        CGRect newFrame = self.frame;
        newFrame.size.height = expectedLabelSize.height;
        self.frame = newFrame;
    }
    
    @end
    
  • 1

    最后,它奏效了 . 感谢你们 .

    我没有让它工作,因为我试图在 heightForRowAtIndexPath 方法中调整标签大小:

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

    (是的,我很傻),我在 cellForRowAtIndexPath 方法中将标签调整为默认值 - 我忽略了我之前写过的代码:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
  • 1

    您可以通过以下方式实现 TableViewController's (UITableViewCell *)tableView:cellForRowAtIndexPath 方法(例如):

    #define CELL_LABEL_TAG 1
    
    - (UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        NSString *text = @"my long text";
    
        static NSString *MyIdentifier = @"MyIdentifier";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero  reuseIdentifier:identifier] autorelease];
        }
    
        CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
        CGFloat height = [self textHeight:text] + 10;
        CGRect frame = CGRectMake(10.0f, 10.0f, width, height);
    
        UILabel *cellLabel = [[UILabel alloc] initWithFrame:frame];
        cellLabel.tag = CELL_LABEL_TAG;
        cellLabel.textColor = [UIColor blackColor];
        cellLabel.backgroundColor = [UIColor clearColor];
        cellLabel.textAlignment = UITextAlignmentLeft;
        cellLabel.font = [UIFont systemFontOfSize:12.0f];
        [cell.contentView addSubview:cellLabel];
        [cellLabel release];
    
        return cell;
    }
    
    UILabel *label = (UILabel *)[cell viewWithTag:CELL_LABEL_TAG];
    label.text = text;
    label.numberOfLines = 0;
    [label sizeToFit];
    return cell;
    

    也可以使用 NSStringsizeWithFont:constrainedToSize:lineBreakMode: 方法计算文本的高度 .

  • 35

    对于那些迁移到iOS 8的人来说,这里是Swift的类扩展:

    extension UILabel {
    
        func autoresize() {
            if let textNSString: NSString = self.text {
                let rect = textNSString.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max),
                    options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                    attributes: [NSFontAttributeName: self.font],
                    context: nil)
                self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, rect.height)
            }
        }
    
    }
    
  • 2

    对我有用的最简单和更好的方法是将高度约束应用于标签并在故事板中设置 priority to low ,即(250) .

    所以你不必担心以编程方式计算高度和宽度,这要归功于故事板 .

  • 4

    更新方法

    + (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
    
        CGSize constraint = CGSizeMake(width, 20000.0f);
        CGSize size;
    
        CGSize boundingBox = [text boundingRectWithSize:constraint
                                                      options:NSStringDrawingUsesLineFragmentOrigin
                                                   attributes:@{NSFontAttributeName:font}
                                                      context:nil].size;
    
        size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
    
        return size.height;
    }
    
  • 2

    谢谢你的这篇文章 . 它对我帮助很大 . 在我的情况下,我也在一个单独的视图控制器中编辑文本 . 我注意到当我使用时:

    [cell.contentView addSubview:cellLabel];
    

    在tableView:cellForRowAtIndexPath:方法中,每次编辑单元格时,标签视图都会在上一个视图的顶部连续呈现 . 文本变为像素化,当删除或更改某些内容时,在新版本下可以看到以前的版本 . 这是我解决问题的方法:

    if ([[cell.contentView subviews] count] > 0) {
        UIView *test = [[cell.contentView subviews] objectAtIndex:0];
        [test removeFromSuperview];
    }
    [cell.contentView insertSubview:cellLabel atIndex:0];
    

    没有更奇怪的分层 . 如果有更好的方法来解决这个问题,请告诉我 .

  • 1
    UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10,100, 200.0f)];
    itemTitle.text = @"aseruy56uiytitfesh";
    itemTitle.adjustsFontSizeToFitWidth = NO;
    itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
    itemTitle.textColor = [UIColor blackColor];
    itemTitle.shadowColor = [UIColor whiteColor];
    itemTitle.shadowOffset = CGSizeMake(0, 1);
    itemTitle.backgroundColor = [UIColor blueColor];
    itemTitle.lineBreakMode = UILineBreakModeWordWrap;
    itemTitle.numberOfLines = 0;
    [itemTitle sizeToFit];
    [self.view addSubview:itemTitle];
    

    在这里使用这一切在标签上使用属性并通过将itemTitle.text中的文本增加为来测试它

    itemTitle.text = @"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv";
    

    它将根据您的需要显示perfetc答案

  • 1

    您也可以将它用作方法 . @Pyjamasam非常真实,所以我只是制作它的方法 . 对其他人来说,这可能会有所帮助

    -(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;
    }
    

    并设置它像这样

    label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];
    
  • 4

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

    有趣的行是 sizeToFit() 并且将 frame.size.height 设置为最大浮点数,这将为长文本提供空间,但 sizeToFit() 将强制它仅使用必要的,但 ALWAYS 在设置 .frame.size.height 后调用它 .

    我建议设置 .backgroundColor 用于调试目的,这样您就可以看到为每种情况呈现的帧 .

  • 2

    要在Swift3中执行以下操作,请执行以下操作:

    let labelSizeWithFixedWith = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
                let exactLabelsize = self.label.sizeThatFits(labelSizeWithFixedWith)
                self.label.frame = CGRect(origin: CGPoint(x: 20, y: 20), size: exactLabelsize)
    
  • 2

    这是使用Objective-c获取UILabel高度的一行代码:

    labelObj.numberOfLines = 0;
    CGSize neededSize = [labelObj sizeThatFits:CGSizeMake(screenWidth, CGFLOAT_MAX)];
    

    并使用.height,您将获得标签的高度,如下所示:

    neededSize.height
    
  • 32
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        cellIdentifier = @"myCell";
        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        cell.myUILabel.lineBreakMode = UILineBreakModeWordWrap;        
        cell.myUILabel.numberOfLines = 0;
        cell.myUILabel.text = @"Some very very very very long text....."
        [cell.myUILabel.criterionDescriptionLabel sizeToFit];    
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
        CGFloat rowHeight = cell.myUILabel.frame.size.height + 10;
    
        return rowHeight;    
    }
    
  • 6
    NSString *str = @"Please enter your text......";
    CGSize lblSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize: CGSizeMake(200.0f, 600.0f) lineBreakMode: NSLineBreakByWordWrapping];
    
    UILabel *label = [[UILabel alloc]init];
    label.frame = CGRectMake(60, 20, 200, lblSize.height);
    label.numberOfLines = 0;
    label.lineBreakMode = NSLineBreakByWordWrapping;
    label.font = [UIFont systemFontOfSize:15];
    label.text = str;
    label.backgroundColor = [UIColor clearColor];
    [label sizeToFit];
    [self.view addSubview:label];
    
  • 1

    我的代码:

    UILabel *label      = [[UILabel alloc] init];
    label.numberOfLines = 0;
    label.lineBreakMode = NSLineBreakByWordWrapping;
    label.text          = text;
    label.textAlignment = NSTextAlignmentCenter;
    label.font          = [UIFont fontWithName:_bodyTextFontFamily size:_bodyFontSize];
    
    CGSize size = [label sizeThatFits:CGSizeMake(width, MAXFLOAT)];
    
    
    float height        = size.height;
    label.frame         = CGRectMake(x, y, width, height);
    
  • 6

    这种方法将给出完美的高度

    -(float) getHeightForText:(NSString*) text withFont:(UIFont*) font andWidth:(float) width{
    CGSize constraint = CGSizeMake(width , 20000.0f);
    CGSize title_size;
    float totalHeight;
    
    
    title_size = [text boundingRectWithSize:constraint
                                    options:NSStringDrawingUsesLineFragmentOrigin
                                 attributes:@{ NSFontAttributeName : font }
                                    context:nil].size;
    
    totalHeight = ceil(title_size.height);
    
    CGFloat height = MAX(totalHeight, 40.0f);
    return height;
    }
    
  • 1
    myLabel.text = "your very long text"
    myLabel.numberOfLines = 0
    myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
    

    请在故事板中为UILable设置约束,包括左上角右下角

  • 2

    我计算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
    

    换行功能:

    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
    }
    
  • 12

    加上以上答案:

    这可以通过故事板轻松实现 .

    • 为UILabel设置约束 . (在我的情况下,我做了顶部,左边和固定宽度)

    • 在属性检查器中设置 Number of line to 0

    • 在属性检查器中设置 Line Break to WordWrap .

    UILabel Height Adjust

  • 10

    基于this answer的UILabel扩展 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)
        }
    
    }
    

    可以像:

    self.labelHeightConstraint.constant = self.label.retrieveTextHeight()
    
  • 1

    问题是没有提到的功能是可行的,并且对于某些字符串和字体将返回不正确的高度值 . 特别是归因于文本的失败 .

    唯一可行的解决方案是:https://stackoverflow.com/a/4214978/699944,重点是使用CoreText手动计算每一行的高度以获得正确的大小 . 没有其他已知方法可以做到这一点 .

相关问题