NSAttributedString背景颜色和圆angular
我有一个关于自定义UIView
圆angular和文本背景颜色的问题。
基本上,我需要在自定义UIView中实现像这样的效果(图片附加 – 注意一侧的圆angular):
我正在考虑使用的方法是:
- 使用核心文本来获得字形运行。
- 检查高亮范围。
- 如果当前运行在高亮范围内,在绘制字形运行之前绘制一个带圆angular的背景矩形和所需的填充颜色。
- 绘制字形运行。
不过,我不确定这是否是唯一的解决scheme(或者说这是否是最有效的解决scheme)。
使用UIWebView
不是一个选项,所以我必须在自定义的UIView
做到这一点。
我的问题是,这是最好的方法来使用,我在正确的轨道上? 或者我错过了一些重要的东西,或者错误地做了什么?
在此先感谢您的帮助! 🙂
干杯!
我设法达到了上述效果,所以我想我会给出同样的答案。
如果有人提出更有效的build议,请随时投稿。 我一定会把你的答案标记为正确的。 🙂
为此,您需要将一个“自定义属性”添加到NSAttributedString
。
基本上,这意味着你可以添加任何键值对,只要它是可以添加到NSDictionary
实例的东西。 如果系统不能识别该属性,则不执行任何操作。 作为开发人员,由您提供该属性的自定义实现和行为。
为了这个答案的目的,让我们假设我已经添加了一个名为: @"MyRoundedBackgroundColor"
的自定义属性,其值为[UIColor greenColor]
。
对于下面的步骤,您需要对CoreText
如何完成任务有一个基本的了解。 查看Apple的Core Text Programming Guide了解框架/行/字形运行/字形等。
所以,这里是步骤:
- 创build一个自定义的UIView子类。
- 有一个属性来接受一个
NSAttributedString
。 - 使用该
NSAttributedString
实例创build一个CTFramesetter
。 - 覆盖
drawRect:
方法 - 从
CTFramesetter
创build一个CTFrame
实例。- 您将需要提供一个
CGPathRef
来创buildCTFrame
。 使该CGPath
与您想要绘制文本的框架相同。
- 您将需要提供一个
- 获取当前的graphics上下文并翻转文本坐标系。
- 使用
CTFrameGetLines(...)
,获取刚刚创build的CTFrame
中的所有行。 - 使用
CTFrameGetLineOrigins(...)
,获取CTFrameGetLineOrigins(...)
所有行源。 - 开始
for loop
–CTLine
数组中的每一行… - 使用
CGContextSetTextPosition(...)
将文本位置设置为CTLine
的开头。 - 使用
CTLineGetGlyphRuns(...)
从CTLineGetGlyphRuns(...)
获取所有的Glyph运行(CTRunRef
)。 - 启动另一个
for loop
– CTRun数组中的每个CTRun
… - 使用
CTRunGetStringRange(...)
获取运行的范围。 - 使用
CTRunGetTypographicBounds(...)
获取印刷边界。 - 使用
CTLineGetOffsetForStringIndex(...)
获取运行的x偏移量。 - 使用从上述函数返回的值计算边界矩形(让我们称之为
runBounds
)。- 请记住 –
CTRunGetTypographicBounds(...)
需要指向variables的指针来存储文本的“上升”和“下降”。 你需要添加这些来获得运行高度。
- 请记住 –
- 使用
CTRunGetAttributes(...)
获取运行的属性。 - 检查属性字典是否包含您的属性。
- 如果您的属性存在,计算需要绘制的矩形的边界。
- 核心文本在基线处具有线条起点。 我们需要从文本的最低点拉到最高点。 因此,我们需要调整下降。
- 因此,从我们在步骤16(
runBounds
)中计算出的边界runBounds
减去下降。 - 现在我们有了
runBounds
,我们知道我们要绘制的区域 – 现在我们可以使用任何CoreGraphis
/UIBezierPath
方法绘制和填充具有特定圆angular的矩形。-
UIBezierPath
有一个方便的类方法叫做bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
让我们围绕特定的angular落。 您可以使用第二个参数中的位掩码来指定angular点。
-
- 现在您已经填充了矩形,只需使用
CTRunDraw(...)
绘制字形运行CTRunDraw(...)
。 - 庆祝创造您的习惯属性的胜利 – 喝一杯啤酒或其他东西! :d
关于检测属性范围扩展到多次运行,当第一次运行遇到属性时,可以获得自定义属性的整个有效范围。 如果发现属性的最大有效范围的长度大于运行的长度,则需要在右侧绘制尖angular(对于从左到右的脚本)。 更多math可以让你检测下一行的高光angular落风格。 🙂
附加是效果的截图。 顶部的框是一个标准的UITextView
,为此我设置了属性UITextView
。 底部的方框是使用上述步骤实现的方框。 两个textView都设置了相同的属性string。
再次,如果有比我使用的更好的方法,请让我知道! :d
希望这有助于社区。 🙂
干杯!