我成功地达到了上述效果,所以我想我应该发布一个同样的答案.
如果有人对如何提高效率有任何建议,请随时提供.我一定把你的答案记为正确答案.:)
为此,您需要在NSAttributedString
中添加一个"自定义属性".
基本上,这意味着你可以添加任何键值对,只要它是你可以添加到NSDictionary
个实例中的东西.如果系统不识别该属性,则不会执行任何操作.作为开发人员,您可以为该属性提供自定义实现和行为.
为了回答这个问题,我们假设我添加了一个名为:@"MyRoundedBackgroundColor"
的自定义属性,其值为[UIColor greenColor]
.
对于接下来的步骤,你需要基本了解CoreText
是如何完成任务的.查看Apple's Core Text Programming Guide了解什么是帧/线/字形运行/字形等.
以下是步骤:
- 创建自定义UIView子类.
- 有接受
NSAttributedString
英镑的财产.
- 使用
NSAttributedString
实例创建一个CTFramesetter
.
- 重写
drawRect:
方法
- 从
CTFramesetter
中创建一个CTFrame
实例.
- 获取当前图形上下文并翻转文本坐标系.
- 使用
CTFrameGetLines(...)
,获得刚才创建的CTFrame
中的所有行.
- 使用
CTFrameGetLineOrigins(...)
,获取CTFrame
的所有线原点.
- 开始一个
for loop
-对于CTLine
数组中的每一行...
- 使用
CGContextSetTextPosition(...)
将文本位置设置为CTLine
开头.
- 使用
CTLineGetGlyphRuns(...)
从CTLine
中获得所有字形运行(CTRunRef
).
- 开始另一个
for loop
-对于CTRun
数组中的每一次运行...
- 使用
CTRunGetStringRange(...)
获得 run 范围.
- 使用
CTRunGetTypographicBounds(...)
获得排版边界.
- 使用
CTLineGetOffsetForStringIndex(...)
获取梯段的x偏移.
- 使用上述函数返回的值计算边界rect(我们称之为
runBounds
).
- 使用
CTRunGetAttributes(...)
获取 run 的属性.
- 判断属性字典是否包含您的属性.
- 如果属性存在,请计算需要绘制的矩形的边界.
- 核心文本的线条起点位于基线处.我们需要从文本的最低点到最高点绘制.因此,我们需要根据下降情况进行调整.
- 因此,从我们在步骤16(
runBounds
)中计算的边界矩形中减go 下降.
- Now that we have the
runBounds
, we know what area we want to paint - now we can use any of the CoreGraphis
/UIBezierPath
methods to draw and fill a rect with specific rounded corners.
UIBezierPath
有一个名为bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
的便利类方法,可以让你绕过特定的角落.在第二个参数中使用位掩码指定角点.
- 现在已经填充了矩形,只需使用
CTRunDraw(...)
绘制轮廓线.
- 庆祝胜利,因为它创造了你的自定义属性-喝啤wine 或其他东西!:D
关于检测属性范围扩展到多个运行,当第一次运行遇到该属性时,可以获得自定义属性的整个有效范围.如果发现属性的最大有效范围的长度大于 run 的长度,则需要在右侧绘制锐角(对于从左到右的脚本).更多的数学运算将让你检测到下一行的高亮角样式.:)
附件是效果的截图.顶部的框是标准的UITextView
,我为其设置了AttributeText.底部的框是使用上述步骤实现的框.为两个文本视图设置了相同的属性字符串.
同样,如果有比我使用的方法更好的方法,请务必告诉我!:D
希望这对社区有所帮助.:)
干杯