ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

提前致谢!

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

您设置的标签字体的最小尺寸是多少,请添加。

C
Community

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

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

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

迅速

var adjustsFontSizeToFitWidth: Bool { get set }

Objective-C

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

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

迅速

var allowsDefaultTighteningForTruncation: Bool { get set }

Objective-C

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Source


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

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

https://i.stack.imgur.com/RtcVf.png

行数为 0

换行符:剪辑

自动收缩:最小字体比例 0.25


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

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 ...
l
loki-e

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


只有当我从“Word Wrap”更改为“Clip”时,Autoshrink 才为我工作。
当我将自动换行更改为剪辑时,我实际上能够让它在零行的标签中调整大小。男孩,如果这被记录在案,那就太好了。
N
Naloiko Eugene

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

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

M
Mick MacCallum

你可以这样写

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;为我工作!
C
Community

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

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

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


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

这适用于运行 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
        }

https://i.stack.imgur.com/kXhch.png

https://i.stack.imgur.com/EnTCx.png

https://i.stack.imgur.com/XTkfc.png

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


K
Kosta Eleftheriou

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

https://cdn-images-1.medium.com/max/1600/1*ycfVpMysgKuDgYkwKpuAhA.gif

没有简单的方法解决它,但它绝对是可能的。一种方法是以编程方式尝试不同的字体大小,直到找到适合接近视图边界的字体。您可以使用 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 已私有化或被删除。
N
Nick Yap

在 iOS 9 中,我只需要:

将标签左右的约束添加到superview。在 IB 中将换行模式设置为剪裁。在 IB 中将行数设置为 1。

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


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

我认为您可以在 alloc init Label 之后编写以下代码

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

它很适合我使用它


谢谢,但是据我所知,这不会计算或缩小字体到所需的最小值,还有为什么你的最小字体比正常字体大?
M
Mike Gledhill

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

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

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

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

(叹。)


A
Anand

下面是如何做到这一点。假设以下 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.

嘿,谢谢你的回答,但我不需要计算标签的高度,我有固定的大小,如果需要,我的字体必须变小。
V
Vaibhav Saran

如果 numberOfLines > 1 我所做的事情是这样的,则不起作用 -

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

H
Hadži Lazar Pešić

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

J
Justin Whitney

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

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

Apple Docs 说:

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

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

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


N
Naishta

斯威夫特 4,Xcode 9.4.1

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

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