在 Objective-C 中计算具有不同语言和表情符号的文本的 UILabel 高度

Posted

技术标签:

【中文标题】在 Objective-C 中计算具有不同语言和表情符号的文本的 UILabel 高度【英文标题】:Calculate UILabel height for text with different languages and emojis in Objective-C 【发布时间】:2016-03-27 13:57:34 【问题描述】:

我需要计算可能是英文/表情符号/其他语言的给定文本的帧大小。

我的做法是:

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
NSDictionary *attributes = @NSFontAttributeName: [UIFont systemFontOfSize:fontSize], NSParagraphStyleAttributeName: style;
CGSize rect = [text boundingRectWithSize:CGSizeMake(containerWidth, CGFLOAT_MAX)
                               options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                            attributes:attributes
                               context:nil].size;

只要我不使用表情符号,它就可以正常工作。表情符号行高/字体大小似乎与常规字体不同。

我看到人们尝试以不同的方式解决它,例如: http://youbbe.xyz/issue/4987325/ios-emoji-messed-up-in-uilabel

此解决方案适用于表情符号,但不适用于英文/其他字体。

查看示例图片:

如您所见,仅文本计算良好(第一个框),但文本+表情符号计算不正确(第二个框)。

我真的很惊讶这个问题没有简单的解决方案。 非常感谢您的帮助。

【问题讨论】:

尝试使用以下函数,但您必须使用发送属性文本和 TextVew 的宽度,并且函数返回 textview 的高度 - (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width UITextView *textView = [[UITextView alloc] init]; [textView setAttributedText:text]; CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)]; //textView.textContainerInset = UIEdgeInsetsZero; return size.height+10; 看看这个..article 什么是containerWidth?你在哪里设置?实际设置标签框架的代码是什么样的? 你试过 UITextView 和 sizeToFit() 吗? 尝试使用 textView,我完全没有问题,而且我认为它不会对您产生太大影响... 【参考方案1】:

使用 UILabel 你可以简单地说:

CGSize size = [label sizeThatFits:CGSizeMake(containerWidth, CGFLOAT_MAX)];

你试过吗?我不认为表情符号有不同的行高,而是它们通常占据整个行高。

您可以只说[label sizeToFit];,然后从框架中获取大小(例如CGSize size = label.frame.size;)。这似乎是为不同字体大小获取正确大小的最一致准确的方法。

您可以将一些代码here 复制并粘贴到 Playground 中,然后查看不同的结果。

【讨论】:

我试过了,但它不起作用...我看到很多人的回答方式相同,但没有一个真正有效... 你应该展示你得到了什么以及你期待什么。 如果您不明白问题所在 - 不要打扰回复。正如我不止一次告诉你的那样,你可以阅读主题并查看示例 - sizeToFit 不起作用。 您应该在问题中包含您已经尝试过的内容,以节省时间和挫败感。此外,简单地说“它不起作用”既没有帮助也没有建设性。我提供了在特定条件下工作的代码。您应该更具体地了解它不起作用的条件。例如,iOS 的目标是什么版本?您的视图层次结构的其余部分是什么样的?你用的是什么字符串?从不起作用的代码中得到什么值?你在使用自动布局吗?所有这些事情都可能与您的问题有关。 正如我之前所说的 - 我尝试了此处提供的所有示例。我提供了图像,并提供了确切问题的示例。使用表情符号时 - 高度计算不正确。我没有使用自动布局。我只有一个 UILable。我没有针对任何特定的 ios 版本。【参考方案2】:

一种可能的解决方案是使用属性字符串设置文本并指定段落样式

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 5;
paragraphStyle.lineHeightMultiple = 1.1;
paragraphStyle.maximumLineHeight = 16;

maximumLineHeight 可以限制包含表情符号的行的高度。

【讨论】:

【参考方案3】:

将字符串转换为NSAttributedString,然后使用这个类别:

- (CGFloat)heightForAttributedStringWithEmojisForWidth:(CGFloat)width 
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self);
    CFRange fitRange;
    CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, [self length]), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange);
    CFRelease(framesetter);
    return ceilf(frameSize.height);

【讨论】:

【参考方案4】:
//may be it will help for you
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
    //set the line break mode
    paragraphStyle.lineBreakMode = yourLabel.lineBreakMode;

    NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:yourLabel.font,
                              NSFontAttributeName,
                              paragraphStyle,
                              NSParagraphStyleAttributeName,
                              nil];


    CGRect rect = [yourLabel.text boundingRectWithSize:CGSizeMake(yourLabel.frame.size.width, yourLabel)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:attrDict
                                                  context:nil];
    CGSize size = rect.size;

【讨论】:

正如其他人在这里回答的那样。此解决方案不起作用。【参考方案5】:
+ (CGFloat)heightForText:(NSString *)text 

    CGFloat offset = 5.f;

    UIFont *font = [UIFont systemFontOfSize:textHeight];
    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
    paragraph.lineBreakMode = NSLineBreakByWordWrapping;
    paragraph.alignment = NSTextAlignmentCenter;
    NSDictionary *attributes = [[NSDictionary alloc] initWithObjectsAndKeys:
                            font, NSFontAttributeName,
                            paragraph, NSParagraphStyleAttributeName, nil];

    //size of one field
    CGSize textSize = [text sizeWithAttributes:attributes];

    CGRect textRect = [text boundingRectWithSize:CGSizeMake(320.f - offset * 2.f, CGFLOAT_MAX)
                                     options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                  attributes:attributes
                                     context:nil];

    return CGRectGetHeight(textRect);


【讨论】:

以上是关于在 Objective-C 中计算具有不同语言和表情符号的文本的 UILabel 高度的主要内容,如果未能解决你的问题,请参考以下文章

iOS和watchOS(Objective-C)具有不同方法的相同类对象

初探 Objective-C/C++ 异常处理实现机制

Kafka Sink 如何将字段映射到具有不同主题和表模式名称的数据库

ComputerNode 不显示 Objective-C

如何在objective-c中比较两个具有很多属性的对象

Objective-C:具有拆分视图的 UITabBarController