转:http://blog.csdn.net/jymn_chen/article/details/10949279

之前用Text Kit写Reader的时候,在分页时要计算一段文本的尺寸大小,之前使用了NSString类的sizeWithFont:constrainedToSize:lineBreakMode:方法,但是该方法已经被iOS7 Deprecated了,而iOS7新出了一个boudingRectWithSize:options:attributes:context方法来代替:

很碍眼的黄色警告标志。

先来看看iOS7 SDK包中关于boudingRectWithSize:options:attributes:context方法的定义:

[cpp] view plaincopy
  1. // NOTE: All of the following methods will default to drawing on a baseline, limiting drawing to a single line.
  2. // To correctly draw and size multi-line text, pass NSStringDrawingUsesLineFragmentOrigin in the options parameter.
  3. @interface NSString (NSExtendedStringDrawing)
  4. - (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);
  5. - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);
  6. @end

关于该方法,NSAttributedString其实也有一个同名的方法:

[cpp] view plaincopy
  1. @interface NSAttributedString (NSExtendedStringDrawing)
  2. - (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
  3. - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
  4. @end

该方法在iOS6就可以使用了。

关于该类,有一篇关于NSAttributedString UIKit Additions Reference翻译的文章:http://blog.csdn.net/kmyhy/article/details/8895643

里面就说到了该方法:

boundingRectWithSize:options:context:

返回文本绘制所占据的矩形空间。

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context

参数

size

宽高限制,用于计算文本绘制时占据的矩形块。

The width and height constraints to apply when computing the string’s bounding rectangle.

options

文本绘制时的附加选项。可能取值请参考“NSStringDrawingOptions”。

context

context上下文。包括一些信息,例如如何调整字间距以及缩放。最终,该对象包含的信息将用于文本绘制。该参数可为 nil 。

返回值

一个矩形,大小等于文本绘制完将占据的宽和高。

讨论

可以使用该方法计算文本绘制所需的空间。size 参数是一个constraint ,用于在绘制文本时作为参考。但是,如果绘制完整个文本需要更大的空间,则返回的矩形大小可能比 size 更大。一般,绘制时会采用constraint 提供的宽度,但高度则会根据需要而定。

特殊情况

为了计算文本块的大小,该方法采用默认基线。

如果 NSStringDrawingUsesLineFragmentOrigin未指定,矩形的高度将被忽略,同时使用单线绘制。(由于一个 bug,在 iOS6 中,宽度会被忽略)

兼容性

  • iOS 6.0 以后支持。

声明于

NSStringDrawing.

另外,关于参数(NSStringDrawingOptions)options

[cpp] view plaincopy
  1. typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
  2. NSStringDrawingTruncatesLastVisibleLine = 1 << 5, // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
  3. NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
  4. NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
  5. NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
  6. } NS_ENUM_AVAILABLE_IOS(6_0);

NSStringDrawingTruncatesLastVisibleLine:

如果文本内容超出指定的矩形限制,文本将被截去并在最后一个字符后加上省略号。如果没有指定NSStringDrawingUsesLineFragmentOrigin选项,则该选项被忽略。

NSStringDrawingUsesLineFragmentOrigin:

绘制文本时使用 line fragement origin 而不是 baseline origin。

The origin specified when drawing the string is the line fragment origin and not the baseline origin.

NSStringDrawingUsesFontLeading:

计算行高时使用行距。(译者注:字体大小+行间距=行距)

NSStringDrawingUsesDeviceMetrics:

计算布局时使用图元字形(而不是印刷字体)。

Use the image glyph bounds (instead of the typographic bounds) when computing layout.

简单写了一个Demo来看看该方法的使用,并比较了一下各个options的不同,首先是代码:

[cpp] view plaincopy
  1. NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:textView.text];
  2. textView.attributedText = attrStr;
  3. NSRange range = NSMakeRange(0, attrStr.length);
  4. NSDictionary *dic = [attrStr attributesAtIndex:0 effectiveRange:&range];   // 获取该段attributedString的属性字典
  5. // 计算文本的大小
  6. CGSize textSize = [textView.text boundingRectWithSize:textView.bounds.size // 用于计算文本绘制时占据的矩形块
  7. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading // 文本绘制时的附加选项
  8. attributes:dic        // 文字的属性
  9. context:nil].size; // context上下文。包括一些信息,例如如何调整字间距以及缩放。该对象包含的信息将用于文本绘制。该参数可为nil
  10. NSLog(@"w = %f", textSize.width);
  11. NSLog(@"h = %f", textSize.height);

再看看不同的options下控制台的输出结果:

[cpp] view plaincopy
  1. NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  2. 2013-09-02 21:04:47.470 BoudingRect_i7_Demo[3532:a0b] w = 322.171875
  3. 2013-09-02 21:04:47.471 BoudingRect_i7_Demo[3532:a0b] h = 138.000015
  4. NSStringDrawingUsesLineFragmentOrigin // The specified origin is the line fragment origin, not the base line origin
  5. 2013-09-02 17:35:40.547 BoudingRect_i7_Demo[1871:a0b] w = 318.398438
  6. 2013-09-02 17:35:40.549 BoudingRect_i7_Demo[1871:a0b] h = 69.000000
  7. NSStringDrawingTruncatesLastVisibleLine // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
  8. 2013-09-02 17:37:38.398 BoudingRect_i7_Demo[1902:a0b] w = 1523.408203
  9. 2013-09-02 17:37:38.400 BoudingRect_i7_Demo[1902:a0b] h = 13.800000
  10. NSStringDrawingUsesFontLeading // Uses the font leading for calculating line heights
  11. 2013-09-02 17:40:45.903 BoudingRect_i7_Demo[1932:a0b] w = 1523.408203
  12. 2013-09-02 17:40:45.905 BoudingRect_i7_Demo[1932:a0b] h = 13.800000
  13. NSStringDrawingUsesDeviceMetrics // Uses image glyph bounds instead of typographic bounds
  14. 2013-09-02 17:42:03.283 BoudingRect_i7_Demo[1956:a0b] w = 1523.408203
  15. 2013-09-02 17:42:03.284 BoudingRect_i7_Demo[1956:a0b] h = 13.800000

其中如果options参数为NSStringDrawingUsesLineFragmentOrigin,那么整个文本将以每行组成的矩形为单位计算整个文本的尺寸。(在这里有点奇怪,因为字体高度大概是13.8,textView中大概有10行文字,此时用该选项计算出来的只有5行,即高度为69,而同时使用NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin却可以得出文字刚好有10行,即高度为138,这里要等iOS7官方的文档出来再看看选项的说明,因为毕竟以上文档是iOS6的东西)

如果为NSStringDrawingTruncatesLastVisibleLine或者NSStringDrawingUsesDeviceMetric,那么计算文本尺寸时将以每个字或字形为单位来计算。

如果为NSStringDrawingUsesFontLeading则以字体间的行距(leading,行距:从一行文字的底部到另一行文字底部的间距。)来计算。

各个参数是可以组合使用的,如NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine。

根据该方法我调整了一下Reader的分页方法:(主要是将被iOS7 Deprecated的sizeWithFont:constrainedToSize:lineBreakMode:方法改成了boudingRectWithSize:options:attributes:context:方法来计算文本尺寸)

[cpp] view plaincopy
  1. /* 判断是否需要分页和进行分页动作 */
  2. -(BOOL)paging
  3. {
  4. /* 获取Settings中设定好的字体(主要是获取字体大小) */
  5. static const CGFloat textScaleFactor = 1.; // 设置文字比例
  6. NSString *textStyle = [curPageView.textView tkd_textStyle]; // 设置文字样式
  7. preferredFont_ = [UIFont tkd_preferredFontWithTextStyle:textStyle scale:textScaleFactor]; //设置prferredFont(包括样式和大小)
  8. NSLog(@"paging: %@", preferredFont_.fontDescriptor.fontAttributes); // 在控制台中输出字体的属性字典
  9. /* 设定每页的页面尺寸 */
  10. NSUInteger height = (int)self.view.bounds.size.height - 40.0; // 页面的高度
  11. /* 获取文本的总尺寸 */
  12. NSDictionary *dic = preferredFont_.fontDescriptor.fontAttributes;
  13. CGSize totalTextSize = [bookItem.content.string boundingRectWithSize:curPageView.textView.bounds.size
  14. options:NSStringDrawingUsesLineFragmentOrigin
  15. attributes:dic
  16. context:nil].size;
  17. NSLog(@"w = %f", totalTextSize.width);
  18. NSLog(@"h = %f", totalTextSize.height);
  19. /* 开始分页 */
  20. if (totalTextSize.height < height) {
  21. /* 如果一页就能显示完,直接显示所有文本 */
  22. totalPages_   = 1;             // 设定总页数为1
  23. charsPerPage_ = [bookItem.content length]; // 设定每页的字符数
  24. textLength_   = [bookItem.content length]; // 设定文本总长度
  25. return NO;                     // 不用分页
  26. }
  27. else {
  28. /* 计算理想状态下的页面数量和每页所显示的字符数量,用来作为参考值用 */
  29. textLength_                       = [bookItem.content length];                   // 文本的总长度
  30. NSUInteger referTotalPages        = (int)totalTextSize.height / (int)height + 1; // 理想状态下的总页数
  31. NSUInteger referCharactersPerPage = textLength_ / referTotalPages;               // 理想状态下每页的字符数
  32. // 输出理想状态下的参数信息
  33. NSLog(@"textLength             = %d", textLength_);
  34. NSLog(@"referTotalPages        = %d", referTotalPages);
  35. NSLog(@"referCharactersPerPage = %d", referCharactersPerPage);
  36. /* 根据referCharactersPerPage和text view的高度开始动态调整每页的字符数 */
  37. // 如果referCharactersPerPage过大,则直接调整至下限值,减少调整的时间
  38. if (referCharactersPerPage > 1000) {
  39. referCharactersPerPage = 1000;
  40. }
  41. // 获取理想状态下的每页文本的范围和pageText及其尺寸
  42. NSRange range       = NSMakeRange(referCharactersPerPage, referCharactersPerPage); // 一般第一页字符数较少,所以取第二页的文本范围作为调整的参考标准
  43. NSString *pageText  = [bookItem.content.string substringWithRange:range]; // 获取该范围内的文本
  44. NSLog(@"%@", pageText);
  45. NSRange ptrange = NSMakeRange(0, pageText.length);
  46. NSDictionary *ptdic = [[bookItem.content attributedSubstringFromRange:ptrange] attributesAtIndex:0 effectiveRange:&ptrange];
  47. CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
  48. options:NSStringDrawingUsesLineFragmentOrigin
  49. attributes:ptdic
  50. context:nil].size;
  51. // 若pageText超出text view的显示范围,则调整referCharactersPerPage
  52. NSLog(@"height = %d", height);
  53. while (pageTextSize.height > height) {
  54. NSLog(@"pageTextSize.height = %f", pageTextSize.height);
  55. referCharactersPerPage -= 2;                                      // 每页字符数减2
  56. range                   = NSMakeRange(0, referCharactersPerPage); // 重置每页字符的范围
  57. ptdic = [[bookItem.content attributedSubstringFromRange:range] attributesAtIndex:0 effectiveRange:&range];
  58. CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
  59. options:NSStringDrawingUsesLineFragmentOrigin
  60. attributes:ptdic
  61. context:nil].size;
  62. pageText                = [bookItem.content.string substringWithRange:range];        // 重置pageText
  63. pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
  64. options:NSStringDrawingUsesLineFragmentOrigin
  65. attributes:ptdic
  66. context:nil].size; // 获取pageText的尺寸
  67. }
  68. // 根据调整后的referCharactersPerPage设定好charsPerPage_
  69. charsPerPage_ = referCharactersPerPage;
  70. NSLog(@"cpp: %d", charsPerPage_);
  71. // 计算totalPages_
  72. totalPages_ = (int)bookItem.content.length / charsPerPage_ + 1;
  73. NSLog(@"ttp: %d", totalPages_);
  74. // 计算最后一页的字符数,防止范围溢出
  75. charsOfLastPage_ = textLength_ - (totalPages_ - 1) * charsPerPage_;
  76. NSLog(@"colp: %d", charsOfLastPage_);
  77. // 分页完成
  78. return YES;
  79. }
  80. }

这样就看不到碍眼的黄色警告标志了。

重要的是,由于该方法计算文本的尺寸更为准确,所以可以使得分页后页与页之间的连贯性好了很多,而且每页的空间利用率都提高了很多,每页的文字几乎铺满了整个页面。

通过boundingRectWithSize:options:attributes:context:计算文本尺寸相关推荐

  1. 计算文本大小,将汉字转拼音

    // 计算文本大小 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17 ...

  2. iOS 动态计算文本内容的高度

    关于ios 下动态计算文本内容的高度,经过查阅和网上搜素,现在看到的有以下几种方法: 1. //  获取字符串的大小  ios6 - (CGSize)getStringRect_:(NSString* ...

  3. [go]根据背景色计算文本颜色

    文章目录 颜色与灰度 互补色与对比色 灰度 透明度混合 Alpha blending Premultiplied Alpha go文本颜色 文本蒙版 在图片中添加文字是常见的操作(如何添加参见< ...

  4. 使用余弦相似度算法计算文本相似度-数学

    20211201 也就是效果 皮尔逊>余弦>欧式 余弦相似度的局限 皮尔逊的优势,相当于是改进版余弦相似度 欧式与 余弦 欧式侧重于直线距离 归一化之后的欧式和余弦的效果也不同 比如 0, ...

  5. 自然语言处理(NLP)之使用TF-IDF模型计算文本相似度

    自然语言处理(NLP)之使用TF-IDF模型计算文本相似度 所用数据集:ChnSentiCorp_htl_all.csv 语料库即存放稀疏向量的列表. 要注意的是,搜索文本text与被检索的文档共用一 ...

  6. Java实现余弦定理计算文本相似度

    相似度度量(Similarity),即计算个体间的相似程度,相似度度量的值越小,说明个体间相似度越小,相似度的值越大说明个体差异越大. 对于多个不同的文本或者短文本对话消息要来计算他们之间的相似度如何 ...

  7. python opencv-4.1.0 cv2.getTextSize()函数 (计算文本字符串的宽度和高度)

    def getTextSize(text, fontFace, fontScale, thickness): # real signature unknown; restored from __doc ...

  8. python计算现场得分_浅谈用 Python 计算文本 BLEU 分数

    浅谈用 Python 计算文本 BLEU 分数 BLEU, 全称为 Bilingual Evaluation Understudy(双语评估替换), 是一个比较候选文本翻译与其他一个或多个参考翻译的评 ...

  9. 深度学习实战-词嵌入计算文本相似性

    使用词嵌入计算文本相似性 文章目录 使用词嵌入计算文本相似性 简介 词嵌入 预训练词嵌入查看文本相似性 Word2vec的数学特性 可视化词嵌入 词嵌入中发现实体类 类内部语义距离 可视化国家数据 补 ...

最新文章

  1. approxPolyDP函数
  2. GitHub图片无法显示
  3. 水晶报表工具栏出现红叉叉无法打印导出等问题的解决方法
  4. 大动作!华为海思注册资本从6亿增加到20亿
  5. 每日站立例会01,02,03
  6. (三)用于构建AI语言翻译系统的工具
  7. Opencv step by step - 图像变换
  8. 学习yii2.0框架阅读代码(九)
  9. 孙鑫VC学习笔记:第六讲 菜单
  10. java 调用bat脚本 等待返回_java程序调用bat脚本
  11. latex 长表格中放入多行公式
  12. 什么是论文查重报告?
  13. web前端开发学习经验分享——css,js进阶篇
  14. 面向对象,继承封装的应用
  15. 华硕笔记本键盘突然个别键失灵
  16. python-二维嵌套列表的元素删除、更改大小写
  17. cocos2dx创造精灵的五种方法
  18. 强化学习:Q-Learning
  19. 大概是全网最详细的Electron ipc 讲解(一)——主进程与渲染进程的两情相悦
  20. weblogic12.1.3applySession在系统修改阶段失败。。。(GDR-70005)

热门文章

  1. leetcode115 不同的子序列
  2. 关于Java中String的问题
  3. redis——实战点赞
  4. 尚硅谷李老师笔记3DQL
  5. Git(9)-diff
  6. 数学建模 割平面算法求解整数规划基本原理与编程实现
  7. C语言 项目 CRM系统(客户信息管理系统)
  8. Ubuntu版本更新一路走来:朕就是这样的汉子
  9. HEVC/H265 主要设计者谈HEVC/H265
  10. 解决:Unknown custom element: <myData> - did you register the component correctly? For recursive compon