【问题标题】:UILabel is not auto-shrinking text to fit label sizeUILabel 不会自动缩小文本以适应标签大小
【发布时间】:2012-04-12 02:15:11
【问题描述】:

我有这个奇怪的问题,我已经处理了 8 个多小时了。根据情况我必须动态计算 UILabels 大小,
例如
我的UIViewController 收到一个事件,我更改UILabels 的大小。从大到小。我的UILabel 的大小变小了,我得到了正确的所需大小,但我的UILabel 中的文本保持不变,字体大小相同等等。我需要字体变小,以适应整个文本UILabel。所以问题是如何使文本适合我的标签与autoshrinking 或类似的东西?

在我的xib 中,UILabels autoshrink 被选中,行数 设置为 0,我的字符串也有换行符 (\n),并且 i'已将 linebreakmode 选择为 wordwrap。也许有人和我现在的情况一样,可以帮助我吗?我真的很感激。

提前致谢!

编辑: UILabel 最小字体大小设置为 10

【问题讨论】:

  • 请添加您设置的标签的最小字体大小。

标签: iphone objective-c ios cocoa-touch ipad


【解决方案1】:

这是怎么做的。假设下面的messageLabel是你想要达到预期效果的标签。现在,试试这些简单的代码行:

    //SET THE WIDTH CONSTRAINTS FOR LABEL.
    CGFloat constrainedWidth = 240.0f;//YOU CAN PUT YOUR DESIRED ONE,THE MAXIMUM WIDTH OF YOUR LABEL.
 //CALCULATE THE SPACE FOR THE TEXT SPECIFIED.
    CGSize sizeOfText=[yourText sizeWithFont:yourFont constrainedToSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
    UILabel *messageLabel=[[UILabel alloc] initWithFrame:CGRectMake(20,20,constrainedWidth,sizeOfText.height)];
    messageLabel.text=yourText;
    messageLabel.numberOfLines=0;//JUST TO SUPPORT MULTILINING.

【讨论】:

  • 嘿,谢谢你的回答,但我不需要计算标签的高度,我有固定的大小,如果需要,我的字体必须变小。
【解决方案2】:

我觉得你可以写下面的代码在alloc init标签之后

UILabel* lbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 280, 50)];
lbl.text = @"vbdsbfdshfisdhfidshufidhsufhdsf dhdsfhdksbf hfsdh fksdfidsf sdfhsd fhdsf sdhfh sdifsdkf ksdhfkds fhdsf dsfkdsfkjdhsfkjdhskfjhsdk fdhsf ";
[lbl setMinimumFontSize:8.0];
[lbl setNumberOfLines:0];
[lbl setFont:[UIFont systemFontOfSize:10.0]];
lbl.lineBreakMode = UILineBreakModeWordWrap;
lbl.backgroundColor = [UIColor redColor];
[lbl sizeToFit];
[self.view addSubview:lbl];

它对我很有效使用它

【讨论】:

  • 谢谢,但这不会计算或缩小字体到我所理解的最小字体,还有为什么你的最小字体比正常字体大?
【解决方案3】:

你可以这样写

UILabel *reviews = [[UILabel alloc]initWithFrame:CGRectMake(14, 13,270,30)];//Set frame
reviews.numberOfLines=0;
reviews.textAlignment = UITextAlignmentLeft;
reviews.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:12];
reviews.textColor=[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.8]; 
reviews.backgroundColor=[UIColor clearColor];

你可以这样计算行数

CGSize maxlblSize = CGSizeMake(270,9999);
CGSize totalSize = [reviews.text sizeWithFont:reviews.font 
              constrainedToSize:maxlblSize lineBreakMode:reviews.lineBreakMode];

CGRect newFrame =reviews.frame;
newFrame.size.height = totalSize.height;
reviews.frame = newFrame;

CGFloat reviewlblheight = totalSize.height;

int lines=reviewlblheight/12;//12 is the font size of label

UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(140,220 , 100, 25);//set frame as your requirement
lbl.font=[UIFont fontWithName:@"Arial" size:20];
[lbl setAutoresizingMask:UIViewContentModeScaleAspectFill];
[lbl setLineBreakMode:UILineBreakModeClip];
lbl.adjustsFontSizeToFitWidth=YES;//This is main for shrinking font
lbl.text=@"HelloHelloHello";

希望这会对您有所帮助:-) 等待您的回复

【讨论】:

  • 所以如果给我的标签设置行数,那么文本会自动收缩吗?
  • 如果您的内容超出宽度,则需要下一行
  • 嘿,我按照你的建议做了,但它不起作用,为什么行数会对我有帮助?
  • 你说得对,我试过它没用,但我找到了适合你的解决方案,就像我的下一个答案一样
  • lbl.adjustsFontSizeToFitWidth=YES;为我工作!
【解决方案4】:

如果numberOfLines > 1 则不起作用 我的所作所为造成了这样的条件-

if(lblRecLocation.text.length > 100)
    lblRecLocation.font = [UIFont fontWithName:@"app_font_name" size:10];

【讨论】:

    【解决方案5】:

    最后我没有找到答案。而且我认为自动收缩不适用于多行。我最终在此链接中使用了建议: autoshrink on a UILabel with multiple lines

    解决方案是在给定宽度下计算文本高度,如果文本较大,则缩小字体大小,然后再次执行相同操作,直到高度等于或小于所需大小。

    我不明白为什么这应该如此难以实施。如果我遗漏了什么,欢迎大家纠正我:)

    【讨论】:

    • 根据此处的其他答案,缺少的关键是您需要将自动换行设置为“剪辑”。这是违反直觉的,但这是让 UILabel 以您想要的方式自动收缩所必需的。这适用于多行 UILabel。
    【解决方案6】:

    如果您仍在寻找更好的解决方案,我认为这就是您想要的:

    一个布尔值,指示是否应减小字体大小以使标题字符串适合标签的边界矩形(此属性仅在 numberOfLines 属性设置为 1 时有效)。

    设置此属性时,minimumScaleFactor 也必须设置(一个好的默认值为 0.5)。

    斯威夫特

    var adjustsFontSizeToFitWidth: Bool { get set }
    

    目标-C

    @property(nonatomic) BOOL adjustsFontSizeToFitWidth;
    

    一个布尔值,指示是否应调整字母之间的间距以适应标签边界矩形内的字符串。

    斯威夫特

    var allowsDefaultTighteningForTruncation: Bool { get set }
    

    目标-C

    @property(nonatomic) BOOL allowsDefaultTighteningForTruncation;
    

    Source.

    【讨论】:

    • 附带说明,minimumFontSize 在 iOS 6.0 中已弃用。请改用minimumScaleFactor
    • 是的,自动收缩不适用于 UILabel 中的多行。试着想象一下:你有多行的文本,你想缩小它以使其“适合”宽度。那么它应该缩小整个文本以适应一行,还是单词保持在同一行并缩小以适应每个宽度?后者是最常见的情况,但不要忘记单词也设置为多行排列。即使禁用了文本的自动排列,您也必须面对具有不同字体大小的文本的每一行,因为并非每个单词都适合宽度。
    • 我认为这个带有Category 的答案非常好,它甚至可能是你已经实现的。这绝对是 Apple API 中缺少的东西,或者他们只是不认为缩小应该是多行 static text 的常见用例。
    • 嗯,是的,这是一个很好的观点,但无论如何,我认为如果我将行数设置为 0,这是一种明确的声明,即可能有一行或多行。我猜想,自动收缩可能会受到行号的影响。但无论如何,感谢您清除问题。我以为我做错了什么。一个类别是个好主意,我想我会在其他需要这个的项目中这样做。感谢您的帮助,祝您好运;)
    • @lester 它应该缩小,以便整个文本在给定当前尺寸的标签声明的行数中可见。它不需要尝试使每条线的大小不同。我真的很惊讶它无法解决这个问题。因此,如果我有一个(可能)长字符串要显示,我可以 either 有多行或让它自动调整大小,而不是两者兼而有之。太可爱了。
    【解决方案7】:

    minimumFontSize 在 iOS 6 中已弃用。

    所以使用minimumScaleFactor 而不是minmimumFontSize

    lbl.adjustsFontSizeToFitWidth = YES
    lbl.minimumScaleFactor = 0.5
    

    斯威夫特 5

    lbl.adjustsFontSizeToFitWidth = true
    lbl.minimumScaleFactor = 0.5
    

    【讨论】:

    • @AntonMatosov,不,它没有!
    • 是的,它确实(现在) - 如果您还将换行符设置为 Truncate Tail 而不是 Word Wrap ...
    【解决方案8】:

    我的解决方案也是 boolean label.adjustsFontSizeToFitWidth = YES; 但。您必须在界面生成器中将自动换行切换到“CLIP”。 然后自动收缩标签。这很重要。

    【讨论】:

    • 只有当我从“Word Wrap”更改为“Clip”时,Autoshrink 才对我有用。
    • 当我将自动换行更改为剪辑时,我实际上能够让它在零行的标签中调整大小。男孩,如果这被记录在案,那就太好了。
    【解决方案9】:

    两年过去了,这个问题仍然存在......

    在 iOS 8 / XCode 6.1 中,我有时会发现我的 UILabel(在 UITableViewCell 中创建,启用了 AutoLayout,并具有灵活的约束,因此它有足够的空间)不会自行调整大小以适应文本字符串。

    和往年一样,解决方案是设置文本,然后然后调用sizeToFit

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        . . .
        cell.lblCreatedAt.text = [note getCreatedDateAsString];
        [cell.lblCreatedAt sizeToFit];
    }
    

    (叹气。)

    【讨论】:

      【解决方案10】:

      这就是我在 iOS 9.2、Xcode 7.2 中获得 UILabel Autoshrink 工作的方式(尤其是在 6s Plus Storyboard 的 4s 设备中的标签字体高度)...

      • 行数为0
      • 换行符:剪辑
      • 自动收缩:最小字体比例 0.25

      【讨论】:

      • 这些是标签实际收缩所需的 3 个成分,我错过了剪辑换行符设置。此外,如果它与其他标签相邻(也可能会自动缩小),则需要设置压缩/拥抱优先级或给出明确的宽度或高度约束。这应该是当前接受的答案。
      • 确保您的标签具有所有约束,尤其是前导和尾随。
      • 我在 Xcode8 中尝试了相同的选项,但发现不起作用。如果有人对此有想法,请帮助我。
      【解决方案11】:

      在 iOS 9 中,我只需要:

      1. 将标签左右两侧的约束添加到superview。
      2. 在 IB 中将换行模式设置为剪辑。
      3. 在 IB 中将行数设置为 1。

      有人建议将行数设置为 0,但对我来说,这只是让标签变为多行...

      【讨论】:

      • 这对我有用。我刚刚在静态单元格中选择了UILabelUITextField,然后单击了“解决自动布局问题”和“添加缺少的约束”。一切都排好了,但 Autoshrink 需要知道到标签的距离,“添加缺少的约束”没有为其添加约束。
      【解决方案12】:

      聚会迟到了,但由于我有每行一个单词的附加要求,所以这一个添加对我有用:

      label.numberOfLines = [labelString componentsSeparatedByString:@" "].count;

      Apple Docs说:

      通常,标签文本是使用您在字体属性中指定的字体绘制的。但是,如果此属性设置为 YES,并且 text 属性中的文本超出标签的边界矩形,则接收器开始减小字体大小,直到字符串适合或达到最小字体大小。 在 iOS 6 及更早版本中,该属性仅在 numberOfLines 属性设置为 1 时有效。

      但这是一个谎言。我告诉你一个谎言!所有 iOS 版本都是如此。具体来说,当在 UICollectionViewCell 中使用 UILabel 时确实如此,其大小由在运行时通过自定义布局动态调整的约束确定(例如 self.menuCollectionViewLayout.itemSize = size)。

      因此,当与adjustsFontSizeToFitWidthminimumScaleFactor 结合使用时,如前面的答案中所述,基于字数以编程方式设置numberOfLines 解决了自动收缩问题。根据字数甚至字符数做类似的事情可能会产生“足够接近”的解决方案。

      【讨论】:

        【解决方案13】:

        这适用于运行 Xcode 8.2.1 (8C1002) 的 Swift 3

        我发现的最佳解决方案是在您的故事板或标签上的 IB 中设置固定宽度。将您的约束设置为约束到边距。在您的 viewDidLoad 中添加以下代码行:

        override func viewDidLoad() {
                    super.viewDidLoad()
        
                    label.numberOfLines = 1
                    label.adjustsFontSizeToFitWidth = true
                    label.minimumScaleFactor = 0.5
                }
        

        这就像一个魅力,它不会溢出到新行,并且会缩小文本以适应标签的宽度,而不会出现任何奇怪的问题,并且可以在 Swift 3 中使用。

        【讨论】:

          【解决方案14】:

          在 Swift 3(以编程方式)中,我必须这样做:

          let lbl = UILabel()
          lbl.numberOfLines = 0
          lbl.lineBreakMode = .byClipping
          lbl.adjustsFontSizeToFitWidth = true
          lbl.minimumScaleFactor = 0.5
          lbl.font = UIFont.systemFont(ofSize: 15)
          

          【讨论】:

            【解决方案15】:

            在 Swift 4 及更高版本中:

            let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200.0, height: 200.0))
            label.adjustsFontSizeToFitWidth = true
            label.numberOfLines = 0
                
            label.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
                
            view.addSubview(label)
            

            【讨论】:

              【解决方案16】:

              这是一个很好的问题,因为现在感觉这将是内置 UIKit 功能或相关框架的一部分。这是该问题的一个很好的视觉示例:

              没有简单的解决方法,但绝对有可能。一种方法是以编程方式尝试不同的字体大小,直到找到适合接近视图边界的字体。您可以使用NSStringNSAttributedStringboundingRect() 函数来完成此操作。例如:

              let string = "This is a test"
              let infiniteSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height:CGFloat.greatestFiniteMagnitude)
              let size = string.boundingRect(with: infiniteSize, options: [], attributes: [.font: UIFont.systemFont(ofSize: avgSize)] context: nil).size
              

              您可以进行二分搜索,使其比完整的蛮力方法更有效。如果您正在寻找真正强大的东西,还有一些需要考虑的因素,包括正确的自动换行和 iOS 字体缓存性能。

              如果您只关心以简单的方式在屏幕上显示文本,我已经在 Swift 中开发了一个强大的实现,我也在生产应用程序中使用它。这是一个UIView 子类,对任何输入文本(包括多行)具有高效、自动的字体缩放功能。要使用它,您只需执行以下操作:

              let view = AKTextView()
              // Use a simple or fancy NSAttributedString
              view.attributedText = .init(string: "Some text here")
              // Add to the view hierarchy somewhere
              

              就是这样!你可以在这里找到完整的源代码:https://github.com/FlickType/AccessibilityKit

              希望这会有所帮助!

              【讨论】:

              • 2018 年 11 月:似乎 FlickType 和 AccessibilityKit 已变为私有或已删除。
              【解决方案17】:

              Swift 4、Xcode 9.4.1

              对我有用的解决方案: 我在集合视图单元格中有一个标签,并且标签文本正在被修剪。 在 Storyboard 上设置如下属性

              Lines = 0
              LineBreak = Word Wrap
              Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
              

              【讨论】:

                猜你喜欢
                • 2012-02-06
                • 1970-01-01
                • 2021-06-28
                • 2019-02-11
                • 1970-01-01
                • 1970-01-01
                • 2020-09-01
                • 2017-12-24
                • 1970-01-01
                相关资源
                最近更新 更多