【问题标题】:How to highlight CoreText with changing highlight colors?如何通过更改突出显示颜色突出显示 CoreText?
【发布时间】:2011-07-21 15:56:55
【问题描述】:

我有一个 UIView 的子类,它实现了绘制 CoreText 的代码。在应用程序中,该 UIView 是在 UIScrollView 中绘制的。这是我目前在 drawRect 中使用的代码:呈现 NSAttributedString:

CGContextRef context = UIGraphicsGetCurrentContext();

float viewHeight = self.bounds.size.height;
CGContextTranslateCTM(context, 0, viewHeight);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0, 1.0));

CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(PADDING_LEFT, -PADDING_TOP, self.bounds.size.width-20.0, self.bounds.size.height);
CGPathAddRect(path, NULL, bounds);

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attrString);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CFRelease(framesetter);
CFRelease(path);
CTFrameDraw(frame, context);

在我的 NSAttributedString 中,我有某些文本属性来为文本着色。

我需要帮助的是概念上的,这应该如何实现?我对绘制框架、图层等的各种方法感到困惑。我尝试查看几本书和其他资源,但我觉得我缺少一些基本的东西。

这是我的要求:

  1. 显然需要在改变方向时将亮点重新绘制到新位置。
  2. 需要能够以编程方式在单个突出显示的基础上更改突出显示颜色。
  3. 为了提高性能,我不想在只更改一个突出显示的突出显示颜色时重新绘制整个 CoreText UIView。
  4. 各个 Rect 必须能够组合在一起以形成单个突出显示,因为突出显示可以覆盖超出单个 CTLine 的范围。
  5. 最终,我想在 CoreText 视图上实现 UIMenuController,所以我认为必须在 CoreText UIView 下方绘制高光?

如果能提供任何帮助,我将不胜感激。

这是我迄今为止尝试过的:

我添加了一个新的 UIView 作为 UIScrollView 的子视图以包含亮点。然后,我为突出显示本身添加单独的 UIView。当我创建虚拟“测试”高亮时,它们会正确显示在 CoreText 视图下。我还可以轻松更改高亮颜色。但是,当我从 CoreText 视图获取有关线条的实际信息以创建真正的高光时,它返回零行。这可能是因为drawRect尚未完成绘制还是其他原因?

这里有一些问题:

  1. 我是否应该将 UIView 作为子视图添加到 UIScrollView 以包含所有亮点,并为每个单独的亮点添加额外的子视图?然后,将每个高亮 UIView 存储在嵌套的 NSArray 中?
  2. 如果我更改 CoreText UIView 下方突出显示的颜色,是否会导致整个 UIView 被重绘?如果是这样,我该如何设计?
  3. 确实,如果我希望 CoreText UIView 接收 UIMenuController 的输入,我必须将高亮对象放在 CoreText UIView 下方?

我看过这个开源项目:

https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML

它的功能令人惊叹,但比我需要的要复杂和详细得多。该代码使用 CoreText 渲染每个单独的字形运行并允许突出显示,这很棒。但是,我正在努力使我的代码保持简单和轻量级。我对 CoreGraphics、CoreAnimation 或 CoreText 知之甚少。

我也看过这个问题:

Core Text - Get Pixel Coordinates from NSRange

该问题的答案提供了用于确定给定行中给定范围的 Rect 边界的调用。我想我可以弄清楚那些电话。

更新

这是我现在所做的。我确定这是错误的,但这是我能找到使其工作的唯一方法......

  1. 创建一个 UIView 作为容器以作为子视图添加到 UIScrollView。
  2. 将 UIView 传递给 CoreTextView。我还将一个字符串范围数组传递给 CoreTextView 以指示应突出显示哪些字符串。
  3. 将 CoreTextView 添加为 UIScrollView 的子视图。这样,UIView 就位于 CoreTextView 之下。
  4. 在CoreTextView的drawRect:函数中,我绘制了CoreText。然后我调用一个函数来计算高光。
  5. 根据行检查每个 NSRange,并计算行中每个匹配项的 CGRect。
  6. CGRect 用于创建新的 UIView。该 UIView 被添加为 UIView 容器的子视图。它还被添加到 NSArray 中,以便我可以跟踪它并根据需要更改单个突出显示的突出显示颜色。

这不会在每次向容器添加高亮或更改颜色时调用 drawRect。但是,我知道这不是一个理想的解决方案。此解决方案的问题:

  1. 当 UIViewController 在 CoreTextView 上调用 setNeedsDisplay 时,无法知道何时完成绘制。我仍然无法找到一种方法来进行回调以告诉 ViewController 可以继续执行下一个任务。
  2. 通过将 UIViews 添加到另一个容器 UIView,drawRect 在技术上是在它自己的矩形之外绘制项目,我知道这是不行的。
  3. 我确信这不是执行此操作的最高效方式,尽管它似乎工作得很好。

【问题讨论】:

    标签: iphone ios uiscrollview core-graphics core-text


    【解决方案1】:

    你的基本想法对于突出显示来说还不错。我不知道它是否真的比在绘制时突出显示字形更容易,但这不是一个坏主意,并且可以轻松打开和关闭突出显示,所以这非常好。

    与其创建大量视图,不如将核心文本放到CALayer 上。然后,您可以创建额外的突出显示层来覆盖文本。这将所有内容都保留在一个视图中。图层比视图便宜得多。如果您只是想进行“荧光笔”样式的高亮,那么您只需为图层设置 backgroundColorframe 即可。

    【讨论】:

    • 谢谢,罗伯!我会考虑切换到使用 CALayers。我对他们没有经验。你知道一个好的资源/书来学习如何使用它们吗?另外,您知道在子视图完成绘制时告诉视图控制器的方法吗?
    • “完成绘图”是什么意思?所有 UIKit 绘图都是在主线程上完成的。如果需要,您可以在后台线程上预先计算所有内容,并让您的视图控制器知道计算已完成。但是你必须在主线程上做 UIKit 绘图。如果您正确地编写代码,CALayer 可以利用后台线程。有关 CALayer 的介绍,请参阅developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/…。当然,当它在今年晚些时候出版时,你可以看到我的书进行广泛讨论:D
    • 再次感谢您的信息。你正在写的书和出版商的名字是什么?我会留意的。也许我没有使用正确的术语。我的问题是我在 ViewController 中的代码在加载 CoreTextView 绘制的新字符串后调用 [CoreTextView setNeedsDisplay] 。当视图完成绘制时,我希望 ViewController 得到通知。也许我应该将 drawRect 代码移动到不同的方法,如“drawText:”,然后调用它而不是 setNeedsDisplay?然后在drawRect:我也可以调用“drawText”吗?我觉得我缺少一些基本的东西。
    • 调用setNeedsDisplay时,系统会在当前事件循环结束时进行绘制。您可以使用[self performSelector:withObject:afterDelay:0] (delay=0) 为“下一个事件循环”安排一些东西,这将始终在绘制视图之后进行,前提是您将自己的代码保留在主线程上。我的书将是 Wiley 的《用 iOS 5 编程推动极限》。 wiley.com/WileyCDA/WileyTitle/productCd-1119961327.html
    • 非常感谢,罗伯。书出来的时候我一定会买的!我得稍微修改一下我的代码,但你肯定帮了大忙!
    猜你喜欢
    • 2010-12-12
    • 2012-10-24
    • 2013-02-02
    • 2023-03-19
    • 2012-03-27
    • 2011-02-02
    • 2012-12-17
    • 1970-01-01
    • 2022-12-05
    相关资源
    最近更新 更多