使用NSStringDrawingTruncatesLastVisibleLine而不是省略号(...)

时间:2018-02-19 19:34:07

标签: ios nsstring ios9 nsattributedstring

我正在尝试使用[NSAttributedString drawWithRect:options:context:]方法在后台渲染一些文字,并且我正在为(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading| NSStringDrawingTruncatesLastVisibleLine | NSLineBreakByWordWrapping)传递选项。如果我的字符串超过两行(我计算了矩形的最大高度),我的文字会被...截断。

但是效果很好,而不是...,我需要使用...more进行截断(最后使用"更多")。

所有渲染必须在后台线程上完成,因此任何UI组件都是不可能的。并且请不要推荐TTTAttributedLabel,因为我首先试图摆脱它,因为它导致在我的应用程序中滚动可怕的性能(已经尝试过)。

在后台线程中绘制字符串时,如何使用自定义截断标记?

1 个答案:

答案 0 :(得分:0)

可能不是最有效的,但我最终是这样的:

  • 检查字符串的大小是否具有所需的宽度和没有高度限制(在绘制方法中使用MAXFLOAT作为边界矩形的高度):

    NSStringDrawingOptions drawingOptions = (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading); [stringToDraw boundingRectWithSize:maximumSize options:drawingOptions context:nil].size;

  • 我知道字体大小,检查结果大小的高度,检查它是否高于预定高度,这表明它是否超过两行。

  • 如果它超过两行,请使用https://stackoverflow.com/a/26806991/811405上的答案的修改版本,获取...more应该大致开始的矩形点处的字符索引( point位于原始文本矩形的第二行右下角附近):

    //this string spans more than two lines.
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    // init text container
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size];
    textContainer.lineFragmentPadding  = 0;
    textContainer.maximumNumberOfLines = 2;
    textContainer.lineBreakMode        = NSLineBreakByClipping;
    [layoutManager addTextContainer:textContainer];
    CGPoint moreStartLocation = CGPointMake(size.width - 60, 30); //35 magic number
    NSUInteger characterIndex = [layoutManager characterIndexForPoint:moreStartLocation
                                                      inTextContainer:textContainer
                             fractionOfDistanceBetweenInsertionPoints:NULL];
    stringToDraw = [attributedString attributedSubstringFromRange:NSMakeRange(0, characterIndex)].mutableCopy;
    [stringToDraw appendAttributedString:self.truncationText];
    size = CGSizeMake(size.width, 35);
    
  • 将原始字符串截断为字符(可选:还可以从限制中找到最后一个空格(例如空格,换行符)字符,并从该点获取子字符串以避免单词剪切)。将“... more”添加到原始字符串。 (文本可以是任何属性,具有任何属性。只需确保它适合两行中的结果矩形。我已将其固定为60px,但也可以获得所需截断字符串的大小,并使用其宽度精确找到最后一个字符)

  • 像往常一样渲染新字符串(以“... more”结尾):

    UIGraphicsBeginImageContextWithOptions(contextSize, YES, 0);
    [stringToDraw drawWithRect:rectForDrawing options:drawingOptions context:nil];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

这个方法的好处在于,由于我们没有触及UIKit(UIGraphics...函数和UIImage是线程安全的),我们可以在后台线程/队列中执行整个过程。我正在使用它在背景中使用属性/链接等预渲染一些文本内容,否则在滚动时在UI线程中占用一两帧,并且它完美地工作。