我有一个关于圆角和定制UIView的文本背景色的问题.

基本上,我需要在自定义UIView中实现如下效果(附图片-注意一侧的圆角):

我认为使用的方法是:

  • 使用核心文本获得字形运行.
  • 判断高光范围.
  • 如果当前梯段在高光范围内,请在绘制轮廓梯段之前,绘制一个具有圆角和所需填充 colored颜色 的背景矩形.
  • 绘制轮廓线.

然而,我不确定这是否是唯一的解决方案(或者说,这是否是最有效的解决方案).

使用UIWebView不是一个选项,所以我必须在定制的UIView中使用.

我的问题是,这是最好的使用方法吗?我走对了吗?还是我错过了一些重要的事情,或者走错了方向?

推荐答案

我成功地达到了上述效果,所以我想我应该发布一个同样的答案.

如果有人对如何提高效率有任何建议,请随时提供.我一定把你的答案记为正确答案.:)

为此,您需要在NSAttributedString中添加一个"自定义属性".

基本上,这意味着你可以添加任何键值对,只要它是你可以添加到NSDictionary个实例中的东西.如果系统不识别该属性,则不会执行任何操作.作为开发人员,您可以为该属性提供自定义实现和行为.

为了回答这个问题,我们假设我添加了一个名为:@"MyRoundedBackgroundColor"的自定义属性,其值为[UIColor greenColor].

对于接下来的步骤,你需要基本了解CoreText是如何完成任务的.查看Apple's Core Text Programming Guide了解什么是帧/线/字形运行/字形等.

以下是步骤:

  1. 创建自定义UIView子类.
  2. 有接受NSAttributedString英镑的财产.
  3. 使用NSAttributedString实例创建一个CTFramesetter.
  4. 重写drawRect:方法
  5. CTFramesetter中创建一个CTFrame实例.
  6. 获取当前图形上下文并翻转文本坐标系.
  7. 使用CTFrameGetLines(...),获得刚才创建的CTFrame中的所有行.
  8. 使用CTFrameGetLineOrigins(...),获取CTFrame的所有线原点.
  9. 开始一个for loop-对于CTLine数组中的每一行...
  10. 使用CGContextSetTextPosition(...)将文本位置设置为CTLine开头.
  11. 使用CTLineGetGlyphRuns(...)CTLine中获得所有字形运行(CTRunRef).
  12. 开始另一个for loop-对于CTRun数组中的每一次运行...
  13. 使用CTRunGetStringRange(...)获得 run 范围.
  14. 使用CTRunGetTypographicBounds(...)获得排版边界.
  15. 使用CTLineGetOffsetForStringIndex(...)获取梯段的x偏移.
  16. 使用上述函数返回的值计算边界rect(我们称之为runBounds).
  17. 使用CTRunGetAttributes(...)获取 run 的属性.
  18. 判断属性字典是否包含您的属性.
  19. 如果属性存在,请计算需要绘制的矩形的边界.
  20. 核心文本的线条起点位于基线处.我们需要从文本的最低点到最高点绘制.因此,我们需要根据下降情况进行调整.
  21. 因此,从我们在步骤16(runBounds)中计算的边界矩形中减go 下降.
  22. 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.
    1. UIBezierPath有一个名为bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:的便利类方法,可以让你绕过特定的角落.在第二个参数中使用位掩码指定角点.
  23. 现在已经填充了矩形,只需使用CTRunDraw(...)绘制轮廓线.
  24. 庆祝胜利,因为它创造了你的自定义属性-喝啤wine 或其他东西!:D

关于检测属性范围扩展到多个运行,当第一次运行遇到该属性时,可以获得自定义属性的整个有效范围.如果发现属性的最大有效范围的长度大于 run 的长度,则需要在右侧绘制锐角(对于从左到右的脚本).更多的数学运算将让你检测到下一行的高亮角样式.:)

附件是效果的截图.顶部的框是标准的UITextView,我为其设置了AttributeText.底部的框是使用上述步骤实现的框.为两个文本视图设置了相同的属性字符串.

同样,如果有比我使用的方法更好的方法,请务必告诉我!:D

希望这对社区有所帮助.:)

干杯

Objective-c相关问答推荐

在没有for循环的情况下获取另一个数组中每个对象的属性值数组

NSNumberFormatter 和 'th' 'st' 'nd' 'rd' (序数)数字结尾

如何更改 UIButton 的突出显示 colored颜色 ?

多个 WKWebView 之间的 Cookie 共享

如何在 Cocoa 中创建字符串的 MD5 哈希?

如何使用 NSString drawInRect 使文本居中?

dispatch_get_global_queue vs dispatch_get_main_queue

判断用户是否在连续的 UISlider 上完成滑动?

在 Objective-C/cocoa 中创建文件夹/目录

如何为图层 shadowOpacity 设置动画?

UILabel 的角半径属性在 iOS 7.1 中不起作用

self.window.rootViewController 与窗口 addSubview

在 Objective C 中使用 extern

如何查看 NSError?

如何以编程方式在 UINavigationController 中按下返回按钮

在 iOS UILabel 上设置 BOLD 字体

通过情节提要加载时如何初始化视图?

如何在不管理 UDID 和重新编译的情况下无线分发 ios 应用程序

UITableView,我如何知道 cellForRowAtIndexPath 期间的哪个部分?

使用 [NSDate date] 获取当前日期和时间