计算 UILabel 文本大小



我正在以编程方式绘制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

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

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

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

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

更新 - 边界矩形与大小输出的示例

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

// 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 = %ftbounds = (%f x %f)",
          fontSize,
          r.size.width,
          r.size.height);
}

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

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)
<</div> div class="one_answers">

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

目标-C

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

斯威夫特 4

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

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

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

CGSize textSize = [label intrinsicContentSize];

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

这是一个快速的变体。

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)

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

如果您的字符串有两行长,则返回的矩形高度约为 33,4 磅。

不要像我一样,把它扔成int,因为 33,4 变成了 33,33 点高度标签从二线传递到一行!

问题

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

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

我对这个问题的解决方案是检查它是否超过,如果没有,那么文本可以适合标签。我通过使用循环来做到这一点。

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 = %ftbounds = (%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);

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

我之所以选择6,是因为我不想让标签太软。

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

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 = %ftbounds = (%f x %f) = %f",
          fontSize,
          r.size.width,
          r.size.height,r.size.width*r.size.height);
    firstVal =r.size.width*r.size.height;
}

其中最后一个循环证明较大的字体可以提供更大的大小结果。

一种使用多行标签 (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

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

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

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

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

Swift 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
}
这是一个

非常丑陋的混乱,因为如果您在使用 attributedString 设置UILabel 字体后对其进行设置 UILabel,它会破坏属性文本中的字体信息,您必须根据文本+字体属性进行计算

曲调的东西

    CGFloat promptLabelMaxWidth = self.promptLabel.frame.size.width;
    NSAttributedString *attributedText = self.promptLabel.attributedText;
    assert(attributedText);
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){promptLabelMaxWidth, CGFLOAT_MAX} options: NSStringDrawingUsesLineFragmentOrigin context:nil];
    NSString *text = self.promptLabel.text;
    UIFont *font = self.promptLabel.font;
    if (font) {
        CGRect r = [text boundingRectWithSize: CGSizeMake(promptLabelMaxWidth, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:@{NSFontAttributeName: font}
                                          context:nil];
        if (r.size.height > rect.size.height) {
            rect = r;
        }
    }

Swift 5:

 func getTextBounds(_ label : UILabel) -> CGRect {
    if label.text != nil && label.font != nil {
        return label.text!.boundingRect(
                      with: CGSize(width: 450, height: 44),
                      options: [],
                      attributes: [NSAttributedString.Key.font : label.font!],
                      context: nil)
    }
    return CGRect.null
}

 func getTextBounds(_ textField : UITextField) -> CGRect {
    if textField.text != nil && textField.font != nil {
        return textField.text!.boundingRect(
                      with: CGSize(width: 450, height: 44),
                      options: [],
                      attributes: [NSAttributedString.Key.font : textField.font!],
                      context: nil)
    }
    return CGRect.null
}

或者,作为扩展:

extension UILabel {
    func textBounds() -> CGRect {
        if self.text != nil && self.font != nil {
            return self.text!.boundingRect(
                          with: CGSize(width: 450, height: 44),
                          options: [],
                          attributes: [NSAttributedString.Key.font : self.font!],
                          context: nil)
        }
        return CGRect.null
    }
}
extension UITextField {
    func textBounds() -> CGRect {
        if self.text != nil && self.font != nil {
            return self.text!.boundingRect(
                          with: CGSize(width: 450, height: 44),
                          options: [],
                          attributes: [NSAttributedString.Key.font : self.font!],
                          context: nil)
        }
        return CGRect.null
    }
}

最新更新