【问题标题】:CoreText Attributed String Height Calculation InaccurateCoreText 属性字符串高度计算不准确
【发布时间】:2014-05-25 04:02:03
【问题描述】:

CoreText 没有给出属性字符串的正确高度(短了一行或更多)。我在 SO 上看到了很多关于此的帖子,但无法理解或找到解决方案。有人可以解释 Core Text 高度计算是如何工作的吗?这是我编写的示例代码,显示了不准确的高度计算。

上下文

我有一个集合视图,其中单元格的高度由其中的内容决定。 我在单元格中显示文本段落。我想通过使用核心文本进行高度计算来节省一些性能。我已经看到,通过核心文本的高度计算,我可以节省大约 300 毫秒。

代码

//高度计算

+ (CGFloat)getHeight
{
    NSString *text = @"The Apple HIG recommends to use a common color for links and buttons and we did just that. By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";

    NSAttributedString *attrStr = [self attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];

    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attrStr));
    CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(frameSetter,
                                                                    CFRangeMake(0, attrStr.length),
                                                                    NULL,
                                                                    CGSizeMake(320, 9999),
                                                                    NULL);

    return suggestedSize.height;
}

// Cell 即将显示时加载相同的文本

- (void)loadData
{
    NSString *text = @"The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";

    NSAttributedString *attrStr = [[self class] attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];

    // UILabel element
    self.textLabel.attributedText = attrStr;

    self.layer.borderColor = [UIColor blueColor].CGColor;
    self.layer.borderWidth = 1.0f;
}

// 生成带前导、字体和换行符的属性字符串

+ (NSAttributedString *)attributedString:(NSString *)string
                        withLinespacing:(CGFloat)linespacing
                      withLineBreakMode:(NSLineBreakMode)lineBreakMode
{
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:string];
    NSInteger strLength = [string length];
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    style.lineSpacing = linespacing;
    style.lineBreakMode = lineBreakMode;

    [attrStr addAttributes:@{NSParagraphStyleAttributeName: style,
                         NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:15]} range:NSMakeRange(0, strLength)];

    return attrStr;
}

上面的代码使用core text计算高度和UILabel来显示文本。 UILabel 对单元格 {Top:17, Leading:13px, Trailing:13px}

有 3 个约束

【问题讨论】:

    标签: ios objective-c uicollectionview core-text


    【解决方案1】:

    CTFramesetterSuggestFrameSizeWithConstraints 已知有问题,返回不正确的高度值。您遇到的缺失行错误非常常见,据我所知,没有好的解决方案,只有丑陋的解决方法,无法提供 100% 准确的结果。

    对于 iOS7 及更高版本,我建议迁移到 TextKit。不知何故,在内部执行的计算确实可以正常工作,同时也基于 Core Text。使用NSLayoutManagerusedRectForTextContainer: 会返回正确的结果。

    您可以看到更完整的答案here。虽然不是 100% 完全在主题上,但有一些关于 Core Text 计算的错误的讨论。

    【讨论】:

    • 感谢 TextKit 提示。我需要在渲染之前计算高度,所以我使用boundingRectForGlyphRange: 进行高度计算。是否可以使用 UILabel 进行渲染(而不是 drawGlyphsForGlyphRange:)?使用 UILabel 和自动布局,由于某种原因,标签的高度小于单元格的高度。
    • @Praveen 有可能,是的。你确定你有正确的设置约束吗?如果你让标签通过内容压缩阻力和内容拥抱的方式调整大小,记得将标签的preferredMaxLayoutWidth属性设置为超级视图的边界宽度(在layoutSubviews中,在调用超级实现之前)。
    • 我正在研究我的限制,但还没有看到我的错误。我在 UICollectionViewCell 中只有一个 UILabel,TopSpace:17,前导和尾随空间为 13。所以基本上 iPhone 的最大宽度只能是 294。标签的内容压缩为 750,内容拥抱为 251。在 layoutSubViews 中调用 super 之前,我还将 preferredMaxLayoutWidth 设置为 294。调用 super 后标签的宽度确实是 294 符合预期。
    • @Praveen 也将内容压缩阻力和拥抱设置为 1000。
    猜你喜欢
    • 1970-01-01
    • 2013-05-24
    • 2020-07-29
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多