在 UITextView 中显示带有超大首字母的文本块

Posted

技术标签:

【中文标题】在 UITextView 中显示带有超大首字母的文本块【英文标题】:Displaying a block of text with an oversized initial letter in a UITextView 【发布时间】:2012-07-02 07:43:42 【问题描述】:

有没有办法在UITextView 中提供这种效果?如果不是,那我怎样才能达到这个效果呢?

【问题讨论】:

核心文本中的首字母大写很奇怪,您必须使用额外的 CTFrameDraw 调用来渲染一个超大的字母。 @CodaFi 嗨,感谢您的回复。您能否详细说明一下,或为此提供任何教程或任何东西? @josh-caswell:感谢您的编辑。 不幸的是,没有。 CoreText 是一个框架的野兽。不过,我可以将您转至docs。 @CodaFi:没问题。感谢您的指导,我将对其进行研究并尝试找到解决方案。谢谢。 【参考方案1】:

出于同样的要求,我创建了一个UIView 子类,它使用首字下沉来绘制文本。文本是使用核心文本绘制的,正如@CodaFi 建议的那样,首字下沉是在单独的核心文本框架中绘制的。

类的完整实现:​​https://gist.github.com/4596476

它的肉看起来像这样:

- (void)drawRect:(CGRect)rect 
    // Create attributed strings
    NSAttributedString *bodyText = [[NSAttributedString alloc] initWithString:[self.text substringWithRange:NSMakeRange(1, self.text.length -1)] attributes:_bodyAttributes];
    NSAttributedString *capText = [[NSAttributedString alloc] initWithString:[[self.text substringWithRange:NSMakeRange(0, 1)] uppercaseString] attributes:_capAttributes];

    CGRect capFrame = CGRectMake(0, 0, [capText size].width, [capText size].height);

    // Set up graphics context
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // Create type frames
    CGMutablePathRef bodyPath = CGPathCreateMutable();
    CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformMakeScale(1, -1), 0, -self.bounds.size.height);
    CGPathMoveToPoint(bodyPath, &transform, CGRectGetMaxX(capFrame), 0);
    CGPathAddLineToPoint(bodyPath, &transform, self.bounds.size.width, 0);
    CGPathAddLineToPoint(bodyPath, &transform, self.bounds.size.width, self.bounds.size.height);
    CGPathAddLineToPoint(bodyPath, &transform, 0, self.bounds.size.height);
    CGPathAddLineToPoint(bodyPath, &transform, 0, CGRectGetMaxY(capFrame));
    CGPathAddLineToPoint(bodyPath, &transform, CGRectGetMaxX(capFrame), CGRectGetMaxY(capFrame));
    CGPathCloseSubpath(bodyPath);

    CGMutablePathRef capPath = CGPathCreateMutable();
    CGPathAddRect(capPath, &transform, CGRectMake(0, 0, capFrame.size.width+10, capFrame.size.height+10));

    // Draw text
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) bodyText);
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), bodyPath, NULL);
    CFRelease(framesetter);
    CTFrameDraw(frame, context);
    CFRelease(frame);
    framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)capText);
    frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), capPath, NULL);
    CFRelease(framesetter);
    CTFrameDraw(frame, context);
    CFRelease(frame);

它的要点是您创建两条路径,一个包含首字下沉的矩形,以及一个为其余文本移除凹口的矩形。 gist 上的完整实现允许您使用属性控制字体、首字下沉周围的间距以及整个视图的内容插入。

它没有实现UITextView 的大部分功能(只有我需要的功能),因此它可能不是一个完整的解决方案。

希望有帮助!

【讨论】:

您好,感谢您的回答。这是您做出的巨大努力。但是我已经用 html 实现了我的这个要求 :)。 是的,这是一个老问题,但希望它对其他人有用!我最初也使用 html,但 webkit 最终对我的应用程序来说太慢了。

以上是关于在 UITextView 中显示带有超大首字母的文本块的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 设置 UITextView 的文本会引发 EXC_BAD_ACCESS

带有可点击链接但没有文本突出显示的 UITextView

UITextView带有可点击链接但没有文字突出显示

带有 NSAttributedString 和 NSTextAttachment 的 UITextView。如何显示文字?

UITextView 在滚动之前不会显示

带有底部边框的自定义 UITextView