UILabel不会自动缩小文本以适合标签大小


119

我有一个奇怪的问题,我要处理超过8个小时。.根据情况,我必须UILabels动态计算大小,
例如,
UIViewController收到一个事件并更改UILabels大小。从大到小。我的大小UILabel变小,我得到正确的所需大小,但是我的文本UILabel保持不变,字体大小不变,依此类推。我需要使字体变小,以使整个文本适合UILabel。所以问题是如何使文本适合我的标签autoshrinking

在my中xibUILabels autoshrink选中,行数也设置为0,并且我的字符串也有新的行符号(\ n),并且我将linebreakmode选择为wordwrap。也许有人处于与我现在相同的状况,并且可以帮助我吗?我真的很感激。

提前致谢!

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


您要设置的标签最小字体是多少?
AJPatel 2012年

Answers:


159

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

一个布尔值,指示是否应减小字体大小以使标题字符串适合标签的边界矩形(此属性仅在将该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;

来源


18
附带说明,minimumFontSizeiOS 6.0中已弃用。使用minimumScaleFactor代替。
lester

14
是的,自动收缩不适用于UILabel中的多行。试想一下:您有多行文字,您想缩小它,使其“适合”宽度。那么,是应该将整个文本缩小以适合一行,还是将单词保留在同一行并缩小以适合每个宽度?后者是最常见的情况,但请不要忘记,单词也设置为多行排列。即使禁用了文本自动排列,您也必须面对文本的每一行具有不同的字体大小,因为并非每个单词都适合宽度。
lester

2
我认为这里的带有类别的答案是相当不错的,无论如何它甚至可能是您已经实现的。这绝对是Apple API中缺少的东西,或者也许他们只是不认为缩小应该是多行静态文本的常见用例。
lester

1
好吧,是的,这是一个好主意,但是无论如何,我认为如果我将行数设置为0,那可以清楚地表明可能存在一行或多行。我估计行数可能会影响自动收缩。但是无论如何,感谢您清除了内容。我以为我做错了什么。进行分类是个好主意,我想我将在需要该项目的其他项目中进行此操作。感谢您的帮助,祝您好运;)
Lukas 2012年

4
@lester它应该缩小,以便在给定当前尺寸的情况下,整个文本在为标签声明的行数中可见。无需尝试使每行具有不同的大小。我真的很惊讶它无法解决这个问题。因此,如果我要显示一个(可能很长)的字符串,则可以多行显示,也可以自动调整大小,不能同时显示两者。这是可爱的。
devios1

125

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

在此处输入图片说明

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

15
这些是标签实际收缩所需的3种成分,我错过了剪切线中断设置。同样,如果它与其他标签相邻(也可能会自动收缩),则需要设置压缩/拥抱优先级,或者给出明确的宽度或高度限制。这应该是当前接受的答案。
Korey Hinton 2015年

3
行数为我做到了!谢谢你
Michael

确保标签具有所有约束,尤其是前导和尾随。
Mashhadi

2
我在Xcode8中尝试了相同的选项,但发现不起作用。如果有人对此有任何想法,请帮助我。
Ganesh

75

minimumFontSize 在iOS 6中已弃用。

所以用minimumScaleFactor代替minmimumFontSize

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

迅捷5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5

好回答。解决了我的问题。谢谢
阿卜杜勒·亚辛2014年

1
@AntonMatosov,不,不是!
Iulian Onofrei,2015年

2
是的,它确实(现在)-如果您还将换行符设置为“截尾”而不是自动换行...
TheEye 2015年

21

我的解决方案也是boolean label.adjustsFontSizeToFitWidth = YES; 但。您必须在Builder界面中将Word Wrapping开关切换到“ CLIP ”。然后自动收缩标签。这个非常重要。


3
只有当我从“自动换行”更改为“剪辑”时,自动收缩功能才对我有用。
NicJ

当我将自动换行更改为剪辑时,我实际上能够在带有零行的标签中调整它的大小。男孩,如果记录下来,那会很好。
DesignedNerd

12

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

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

5

你可以这样写

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";

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


因此,如果将行数设置为标签,文本将自动收缩吗?
卢卡斯2012年

如果您的内容超出宽度,则需要下一行
Birju 2012年

嘿,我已经按照您的建议完成了,但是那行不通,为什么行数对我有帮助?
卢卡斯2012年

您是对的,我尝试了它没有用,但我找到了解决方案,就像我的下一个答案一样
Birju 2012年

lbl.adjustsFontSizeToFitWidth = YES; 为我工作!
开发人员

4

最终我没有找到答案。我认为自动收缩不适用于多行。我最终在此链接中使用了建议: 在多行UILabel上自动收缩

解决方案是计算给定宽度下的文本高度,如果文本较大,则缩小字体大小,然后再次进行调整,直到高度等于或小于所需大小。

我不明白为什么这应该很难实施。如果我缺少什么,欢迎大家纠正我:)


根据此处的其他答案,缺少的关键是您需要将Word Wrapping设置为“ Clip”。这违反直觉,但这是使UILabel以所需方式自动缩小所必需的。这适用于多行UILabel。
邓肯·巴贝奇

4

这是针对运行Xcode 8.2.1(8C1002)的Swift 3

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

override func viewDidLoad() {
            super.viewDidLoad()

            label.numberOfLines = 1
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.5
        }

标签约束到边距

固定宽度标签约束到边距

属性检查器

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


4

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

字体大小调整动画

解决这个问题没有简单的方法,但是绝对有可能。一种方法是以编程方式尝试使用不同的字体大小,直到找到与视图边界相当接近的字体大小为止。您可以使用或boundingRect()功能来完成此操作。例如:NSStringNSAttributedString

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

希望这可以帮助!


1
2018年11月:似乎FlickType和AccessibilityKit已变为私有或已删除。
克里斯·帕维格里奥

3

在iOS 9中,我只需要:

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

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


这对我有用。我刚刚在静态单元格中选择了一个UILabel和一个UITextField,然后单击“解决自动布局问题”和“添加缺少的约束”。一切都准备就绪,但是Autoshrink需要知道到标签的距离,“添加缺失的约束”并没有为其添加约束。
阿德里安

2

我想你可以在分配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];

很好,我可以使用它


1
谢谢,但是根据我的理解,这不会将字体计算或缩小到所需的最小字体,而且为什么您的最小字体比正常字体大?
卢卡斯2012年

2

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

在iOS中8 / 6.1的XCode,我有时发现我UILabel(在创建UITableViewCell,启用了自动布局,并且具有灵活的约束,因此具有足够的空间)无法调整自身大小以适合文本字符串。

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

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

(叹。)


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.

嘿,谢谢你的回答,但是我不需要计算标签的高度,我有固定的大小,根据需要,我的字体必须变小。
卢卡斯2012年

1

如果numberOfLines > 1 我做了这样的条件,将无法正常工作-

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

0

来晚了,但是由于我有每行一个字一个额外的要求,所以这个加法对我有用:

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

苹果文档说:

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

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

因此,如先前的答案所述,当与adjustsFontSizeToFitWidth和结合使用时minimumScaleFactornumberOfLines基于字数的编程设置解决了自动收缩问题。根据字数甚至字符数执行类似的操作可能会产生“足够接近”的解决方案。


0

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

0

斯威夫特4,Xcode 9.4.1

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

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.