ios 计算 UILabel 文本大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19128797/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:56:53  来源:igfitidea点击:

Calculating UILabel Text Size

iosobjective-cuilabelframe

提问by Sarp Kaya

I am drawing UILabelsprogrammatically. They get their sizes from a database. So I cannot just use sizeToFit. I have already implemented a function that redraws UILabelswith a passed ratio. So all I need to find is the text in UILabelfrom my view that would require the maximum ratio to redraw UILabels. So finally I need to do something like this:

我正在以UILabels编程方式绘图。它们从数据库中获取它们的大小。所以我不能只使用sizeToFit. 我已经实现了UILabels一个以传递的比率重绘的函数。所以我需要找到的只是UILabel我认为需要最大比例重绘的文本UILabels。所以最后我需要做这样的事情:

    double ratio = 1.00;
    for (UILabel* labels in sec.subviews) {

        float widthLabel = labels.frame.size.width;
        float heightLabel = labels.frame.size.height;
        float heightText = //get the text height here
        float widthText = //get the text width here
        if (widthLabel < widthText) {
            ratio = MAX(widthText/widthLabel,ratio);
        }
        if (heightLabel < heightText) {
            ratio = MAX(heightText/heightLabel, ratio);
        }
    }
    //redraw UILabels with the given ratio here

So how can I get the height and width size of a text, as some of my text do not fit into the label I cannot simply use label bounds? I am using Xcode 5 and iOS 7.

那么如何获得文本的高度和宽度大小,因为我的一些文本不适合标签,我不能简单地使用标签边界?我正在使用 Xcode 5 和 iOS 7。

采纳答案by Sarp Kaya

The problem with

问题与

CGRect r = [text boundingRectWithSize:CGSizeMake(200, 0)
                              options:NSStringDrawingUsesLineFragmentOrigin
                           attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
                              context:nil];

is boundingRectWithSizewhich determines the maximum value that CGRect can have.

boundingRectWithSize确定 CGRect 可以具有的最大值。

My solution for this problem is to check if it exceeds, if not then text can fit into the label. I did it by using loops.

我对这个问题的解决方案是检查它是否超过,如果没有,则文本可以放入标签中。我是通过使用循环来做到的。

NSString *text = @"This is a long sentence. Wonder how much space is needed?";
CGFloat width = 100;
CGFloat height = 100;
bool sizeFound = false;
while (!sizeFound) {
    NSLog(@"Begin loop");
    CGFloat fontSize = 14;
    CGFloat previousSize = 0.0;
    CGFloat currSize = 0.0;
    for (float fSize = fontSize; fSize < fontSize+6; fSize++) {
        CGRect r = [text boundingRectWithSize:CGSizeMake(width, height)
                                      options:NSStringDrawingUsesLineFragmentOrigin
                                   attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fSize]}
                                      context:nil];
        currSize =r.size.width*r.size.height;
        if (previousSize >= currSize) {
            width = width*11/10;
            height = height*11/10;
            fSize = fontSize+10;
        }
        else {
            previousSize = currSize;
        }
        NSLog(@"fontSize = %f\tbounds = (%f x %f) = %f",
              fSize,
              r.size.width,
              r.size.height,r.size.width*r.size.height);
    }
    if (previousSize == currSize) {
        sizeFound = true;
    }

}
NSLog(@"Size found with width %f and height %f", width, height);

After each iteration the size of height and width increments 10% of its value.

每次迭代后,高度和宽度的大小增加其值的 10%。

The reason why I picked 6 is because I did not want the label to be too squishy.

我选择 6 的原因是因为我不想标签太软。

For a solution that does not use loops:

对于不使用循环的解决方案:

NSString *text = @"This is a long sentence. Wonder how much space is needed?";
CGFloat width = 100;
CGFloat height = 100;

CGFloat currentFontSize = 12;
CGRect r1 = [text boundingRectWithSize:CGSizeMake(width, height)
                              options:NSStringDrawingUsesLineFragmentOrigin
                           attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize+6]}
                              context:nil];

CGRect r2 = [text boundingRectWithSize:CGSizeMake(width, height)
                               options:NSStringDrawingUsesFontLeading
                            attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize+6]}
                               context:nil];

CGFloat firstVal =r1.size.width*r1.size.height;
CGFloat secondVal =r2.size.width*r2.size.height;

NSLog(@"First val %f and second val is %f", firstVal, secondVal);

if (secondVal > firstVal) {
    float initRat = secondVal/firstVal;

    float ratioToBeMult = sqrtf(initRat);

    width *= ratioToBeMult;
    height *= ratioToBeMult;
}

NSLog(@"Final width %f and height %f", width, height);

//for verifying
for (NSNumber *n in @[@(12.0f), @(14.0f), @(17.0f)]) {
    CGFloat fontSize = [n floatValue];
    CGRect r = [text boundingRectWithSize:CGSizeMake(width, height)
                                  options:NSStringDrawingUsesLineFragmentOrigin
                               attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
                                  context:nil];
    NSLog(@"fontSize = %f\tbounds = (%f x %f) = %f",
          fontSize,
          r.size.width,
          r.size.height,r.size.width*r.size.height);
    firstVal =r.size.width*r.size.height;
}

Where the last loop is proof that larger font can give a higher size result.

最后一个循环证明较大的字体可以产生更大的尺寸结果。

回答by XJones

All of the [NSString sizeWithFont...]methods are deprecated in iOS 7. Use this instead.

所有这些[NSString sizeWithFont...]方法在 iOS 7 中都已弃用。请改用它。

CGRect labelRect = [text
                    boundingRectWithSize:labelSize
                    options:NSStringDrawingUsesLineFragmentOrigin
                    attributes:@{
                     NSFontAttributeName : [UIFont systemFontOfSize:14]
                    }
                    context:nil];

Also see https://developer.apple.com/documentation/foundation/nsstring/1619914-sizewithfont.

另请参阅https://developer.apple.com/documentation/foundation/nsstring/1619914-sizewithfont

UPDATE - example of boundingRectWithSize output

UPDATE - boundingRectWithSize 输出示例

Per your comment I did a simple test. The code and output is below.

根据您的评论,我做了一个简单的测试。代码和输出如下。

// code to generate a bounding rect for text at various font sizes
NSString *text = @"This is a long sentence. Wonder how much space is needed?";
for (NSNumber *n in @[@(12.0f), @(14.0f), @(18.0f)]) {
    CGFloat fontSize = [n floatValue];
    CGRect r = [text boundingRectWithSize:CGSizeMake(200, 0)
                                  options:NSStringDrawingUsesLineFragmentOrigin
                               attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
                                  context:nil];
    NSLog(@"fontSize = %f\tbounds = (%f x %f)",
          fontSize,
          r.size.width,
          r.size.height);
}

this produces the following output (note that the bounds change as expected as the font size gets larger):

这会产生以下输出(请注意,随着字体大小变大,边界会按预期变化):

fontSize = 12.000000    bounds = (181.152008 x 28.632000)
fontSize = 14.000000    bounds = (182.251999 x 50.105999)
fontSize = 18.000000    bounds = (194.039993 x 64.421997)

回答by H. Serdar ??nar

Length gets the number of characters. If you want to get the width of the text:

Length 获取字符数。如果要获取文本的宽度:

Objective-C

目标-C

CGSize textSize = [label.text sizeWithAttributes:@{NSFontAttributeName:[label font]}];

Swift 4

斯威夫特 4

let size = label.text?.size(withAttributes: [.font: label.font]) ?? .zero

This gets you the size. And you can compare the textSize.widthof each label.

这让你知道大小。您可以比较textSize.width每个标签的 。

回答by poff

Another simple way to do this that I haven't seen mentioned yet:

另一种我还没有提到的简单方法:

CGSize textSize = [label intrinsicContentSize];

(This only works correctly after you have set the label's text and font, of course.)

(当然,这只有在您设置了标签的文本和字体后才能正常工作。)

回答by Collin

Here is a swift variant.

这是一个快速的变体。

let font = UIFont(name: "HelveticaNeue", size: 25)!
let text = "This is some really long text just to test how it works for calculating heights in swift of string sizes. What if I add a couple lines of text?"

let textString = text as NSString

let textAttributes = [NSFontAttributeName: font]

textString.boundingRectWithSize(CGSizeMake(320, 2000), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)

回答by Martin

Little advice guys, if like me you're using, boundingRectWithSizewith [UIFont systemFontOFSize:14]

小建议家伙,如果像我一样你正在使用,boundingRectWithSize[UIFont systemFontOFSize:14]

If your string is two lines long, the returned rect height is something like 33,4 points.

如果您的字符串长两行,则返回的矩形高度类似于 33,4 点。

Don't make the mistake, like me, to cast it into an int, because 33,4 becomes 33, and 33 points height label pass from two to one line!

不要像我一样错误地将其转换为int,因为 33,4 变成了 33,并且 33 点高度标签从两行变成了一行!

回答by Ramakrishna

By using this line of code we can get the size of text on the label.

通过使用这行代码,我们可以获得标签上文本的大小。

let str = "Sample text"
let size = str.sizeWithAttributes([NSFontAttributeName:UIFont.systemFontOfSize(17.0)])

So, we can use the both width and height.

所以,我们可以同时使用宽度和高度。

回答by chrisben

A solution that works with multiline labels (Swift 4), to calculate the height from a fixed width:

使用多行标签(Swift 4)的解决方案,以从固定宽度计算高度:

let label = UILabel(frame: .zero)
label.numberOfLines = 0 // multiline
label.font = UIFont.systemFont(ofSize: UIFont.labelFontSize) // your font
label.preferredMaxLayoutWidth = width // max width
label.text = "This is a sample text.\nWith a second line!" // the text to display in the label

let height = label.intrinsicContentSize.height

回答by Jayesh Miruliya

msgStr string get size :

msgStr 字符串获取大小:

let msgStr:NSString = Data["msg"]! as NSString
let messageSize = msgStr.boundingRect(with: CGSize(width: ChatTable.frame.width-116, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName:UIFont(name: "Montserrat-Light", size: 14)!], context: nil).size

回答by Abhishek Jain

Swift 3.0

斯威夫特 3.0

func getLabelHeight() -> CGFloat {
    let font = UIFont(name: "OpenSans", size: 15)!
    let textString = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." as NSString

    let textAttributes = [NSFontAttributeName: font]

    let rect = textString.boundingRect(with: CGSize(width: 320, height: 2000), options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil)
    return rect.size.height
}