通过boundingRectWithSize:options:attributes:context:计算文本尺寸

转: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.   
  5. NSStringDrawingUsesLineFragmentOrigin // The specified origin is the line fragment origin, not the base line origin  
  6. 2013-09-02 17:35:40.547 BoudingRect_i7_Demo[1871:a0b] w = 318.398438  
  7. 2013-09-02 17:35:40.549 BoudingRect_i7_Demo[1871:a0b] h = 69.000000  
  8.   
  9. 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.  
  10. 2013-09-02 17:37:38.398 BoudingRect_i7_Demo[1902:a0b] w = 1523.408203  
  11. 2013-09-02 17:37:38.400 BoudingRect_i7_Demo[1902:a0b] h = 13.800000  
  12.   
  13. NSStringDrawingUsesFontLeading // Uses the font leading for calculating line heights  
  14. 2013-09-02 17:40:45.903 BoudingRect_i7_Demo[1932:a0b] w = 1523.408203  
  15. 2013-09-02 17:40:45.905 BoudingRect_i7_Demo[1932:a0b] h = 13.800000  
  16.   
  17. NSStringDrawingUsesDeviceMetrics // Uses image glyph bounds instead of typographic bounds  
  18. 2013-09-02 17:42:03.283 BoudingRect_i7_Demo[1956:a0b] w = 1523.408203  
  19. 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.       
  11.     /* 设定每页的页面尺寸 */  
  12.     NSUInteger height = (int)self.view.bounds.size.height - 40.0; // 页面的高度  
  13.       
  14.       
  15.     /* 获取文本的总尺寸 */  
  16.     NSDictionary *dic = preferredFont_.fontDescriptor.fontAttributes;  
  17.     CGSize totalTextSize = [bookItem.content.string boundingRectWithSize:curPageView.textView.bounds.size  
  18.                                                                  options:NSStringDrawingUsesLineFragmentOrigin  
  19.                                                               attributes:dic  
  20.                                                                  context:nil].size;  
  21.     NSLog(@"w = %f", totalTextSize.width);  
  22.     NSLog(@"h = %f", totalTextSize.height);  
  23.       
  24.       
  25.     /* 开始分页 */  
  26.     if (totalTextSize.height < height) {  
  27.         /* 如果一页就能显示完,直接显示所有文本 */  
  28.         totalPages_   = 1;             // 设定总页数为1  
  29.         charsPerPage_ = [bookItem.content length]; // 设定每页的字符数  
  30.         textLength_   = [bookItem.content length]; // 设定文本总长度  
  31.         return NO;                     // 不用分页  
  32.     }  
  33.     else {  
  34.         /* 计算理想状态下的页面数量和每页所显示的字符数量,用来作为参考值用 */  
  35.         textLength_                       = [bookItem.content length];                   // 文本的总长度  
  36.         NSUInteger referTotalPages        = (int)totalTextSize.height / (int)height + 1; // 理想状态下的总页数  
  37.         NSUInteger referCharactersPerPage = textLength_ / referTotalPages;               // 理想状态下每页的字符数  
  38.         // 输出理想状态下的参数信息  
  39.         NSLog(@"textLength             = %d", textLength_);  
  40.         NSLog(@"referTotalPages        = %d", referTotalPages);  
  41.         NSLog(@"referCharactersPerPage = %d", referCharactersPerPage);  
  42.           
  43.           
  44.         /* 根据referCharactersPerPage和text view的高度开始动态调整每页的字符数 */  
  45.         // 如果referCharactersPerPage过大,则直接调整至下限值,减少调整的时间  
  46.         if (referCharactersPerPage > 1000) {  
  47.             referCharactersPerPage = 1000;  
  48.         }  
  49.           
  50.         // 获取理想状态下的每页文本的范围和pageText及其尺寸  
  51.         NSRange range       = NSMakeRange(referCharactersPerPage, referCharactersPerPage); // 一般第一页字符数较少,所以取第二页的文本范围作为调整的参考标准  
  52.         NSString *pageText  = [bookItem.content.string substringWithRange:range]; // 获取该范围内的文本  
  53.         NSLog(@"%@", pageText);  
  54.           
  55.           
  56.         NSRange ptrange = NSMakeRange(0, pageText.length);  
  57.         NSDictionary *ptdic = [[bookItem.content attributedSubstringFromRange:ptrange] attributesAtIndex:0 effectiveRange:&ptrange];  
  58.         CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size  
  59.                                                      options:NSStringDrawingUsesLineFragmentOrigin  
  60.                                                   attributes:ptdic  
  61.                                                      context:nil].size;  
  62.           
  63.         // 若pageText超出text view的显示范围,则调整referCharactersPerPage  
  64.         NSLog(@"height = %d", height);  
  65.         while (pageTextSize.height > height) {   
  66.             NSLog(@"pageTextSize.height = %f", pageTextSize.height);  
  67.             referCharactersPerPage -= 2;                                      // 每页字符数减2  
  68.             range                   = NSMakeRange(0, referCharactersPerPage); // 重置每页字符的范围  
  69.             ptdic = [[bookItem.content attributedSubstringFromRange:range] attributesAtIndex:0 effectiveRange:&range];  
  70.             CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size  
  71.                                                          options:NSStringDrawingUsesLineFragmentOrigin  
  72.                                                       attributes:ptdic  
  73.                                                          context:nil].size;  
  74.             pageText                = [bookItem.content.string substringWithRange:range];        // 重置pageText  
  75.               
  76.             pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size  
  77.                                                   options:NSStringDrawingUsesLineFragmentOrigin  
  78.                                                attributes:ptdic  
  79.                                                   context:nil].size; // 获取pageText的尺寸  
  80.         }  
  81.           
  82.         // 根据调整后的referCharactersPerPage设定好charsPerPage_  
  83.         charsPerPage_ = referCharactersPerPage;   
  84.         NSLog(@"cpp: %d", charsPerPage_);  
  85.           
  86.         // 计算totalPages_  
  87.         totalPages_ = (int)bookItem.content.length / charsPerPage_ + 1;  
  88.         NSLog(@"ttp: %d", totalPages_);  
  89.           
  90.         // 计算最后一页的字符数,防止范围溢出  
  91.         charsOfLastPage_ = textLength_ - (totalPages_ - 1) * charsPerPage_;  
  92.         NSLog(@"colp: %d", charsOfLastPage_);  
  93.           
  94.         // 分页完成  
  95.         return YES;  
  96.     }  
  97. }  

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

 

 


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


 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动后端支持平台Parse将API由Ruby迁移到Go

Charity Majors是移动后端支持平台Parse的工程师。近日&#xff0c;他撰文介绍了他们将API从Ruby迁移到Go的过程。\\2011年&#xff0c;Parse借助Ruby on Rails快速推出了第一个版本。他们用Unicorn作为HTTP服务器&#xff0c;用Capistrano部署代码&#xff0c;用RVM管理环境&a…

linux 虚拟钢琴程序,基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现,为乐器演奏(如钢琴、吉他)...

基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)2016-08-22 0 0 0 4.0分其他1积分下载如何获取积分&#xff1f;基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)提供稳定&#xff0c;丰富…

一个从源代码里提取中文字符串的java类

2019独角兽企业重金招聘Python工程师标准>>> 工作中需要优化代码里的中文警示语和异常信息&#xff0c;实在比较多&#xff0c;所以就写了个程序专门从代码里提取中文字符串。 java做的&#xff0c;比较简单&#xff0c;放上来备忘 package com.extractstr.app;impo…

oracle RAC切换归档

&#xff08;转自leshami&#xff09; RAC环境下的归档模式切换与单实例稍有不同&#xff0c;主要是共享存储所产生的差异。在这种情况下&#xff0c;我们可以将RAC数据库切换到非集群状态下&#xff0c;仅仅在一个实例上来实施归档模式切换即可完成RAC数据库的归档模式转换问…

linux启用ipmi服务,使用 ipmitool 实现 Linux 系统下对服务器的 ipmi 管理

简介&#xff1a; IPMI 是一种可扩展的标准&#xff0c;它定义了如何监控硬件和传感器、控制系统部件以及记录重大事件&#xff0c;随着 ipmi 技术在服务器中的应用&#xff0c;利用 ipmi 的众多优势就成为服务器管理特别是集群管理中不可缺少的部分。本文首先介绍了 ipmi 的一…

linux中bc用法英文,使用GNU bc在Linux Shell中进行数学运算

在 shell 中使用 bc 更好地做算数&#xff0c;它是一种用于高级计算的数学语言。大多数 POSIX 系统带有 GNU bc&#xff0c;这是一种任意精度的数字处理语言。它的语法类似于 C&#xff0c;但是它也支持交互式执行语句和处理来自标准输入(stdin)的数据。因此&#xff0c;它通常…

Linux C Socket编程原理及简单实例

部分转自&#xff1a;http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1. 什么是TCP/IP、UDP&#xff1f; 2. Socket在哪里呢&#xff1f; 3. Socket是什么呢&#xff1f; 4. 有很多的框架&#xff0c;为什么还在从Socket开始&#xff1f; 5. Linux C…

蜉蝣极客

蜉蝣极客 百科名片 蜉蝣目&#xff08;英文&#xff1a;mayfly&#xff0c;学名&#xff1a;Ephemeroptera&#xff09;通称蜉蝣&#xff0c;具有古老而特殊的性状&#xff0c;是最原始的有翅昆虫。和蜻蜓目可同分为古翅次纲&#xff0c;他们的翅不能折叠。蜉蝣目昆虫体形细长…

解决Web部署 svg/woff/woff2字体 404错误

原文:解决Web部署 svg/woff/woff2字体 404错误问题&#xff1a;最近在IIS上部署web项目的时候&#xff0c;发现浏览器总是报找不到woff、woff2字体的错误。导致浏览器加载字体报404错误&#xff0c;白白消耗了100-200毫秒的加载时间。 原因&#xff1a;因为服务器IIS不认SVG&am…

压缩感知先进——关于稀疏矩阵

前《初识压缩感知Compressive Sensing》中我们已经讲过了压缩感知的作用和基本想法&#xff0c;涉及的领域&#xff0c;本文通过学习陶哲轩对compressive sensing&#xff08;CS&#xff09;的课程&#xff0c;对压缩感知做进一步理解。针对其原理做出解说。本文较为理论性&…

基于环信sdk的陌生人交友php服务器代码开源

2019独角兽企业重金招聘Python工程师标准>>> 这个是代码结构 服务器端需要两个服务器端软件的支持&#xff1a; 1&#xff1a;weed-fs golang写的海量小文件存储工具 2&#xff1a;memcache 流行的缓存服务器 服务器端主要配置是 conf.php 文件&#xff0c;配置数据…

Linux视频 pad,Wine 1.9.10 发布下载, 改善视频输出

Wine 1.9.10最近发布下载&#xff0c;改进了大量的新功能和错误修正。一个显著的更新是此版本改善视频输出&#xff0c;更兼容目录列表&#xff0c;修复一些C 运行时。Wine 1.9.10 Bug 修复Month calendar control uses 0sunday for firstDayOfWeektooltips not working proper…

EXCEL数据导入dataset

一、开工必备 1、micorosoft office2007 2、VS2010、Oracle 11 二、界面 三、内部代码 (1)获取数据库连接&#xff0c;定义全局变量 private static string connString System.Configuration.ConfigurationSettings.AppSettings[ "connStr" ]; D…

JDBC连接MySQL数据库及演示样例

JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术。 一、JDBC基础知识 JDBC&#xff08;Java Data Base Connectivity,java数据库连接&#xff09;是一种用于执行SQL语句的Java API&#xff0c;能够为多种关系数据库提供统一訪问&#xff0c;它由一组用Java语言…

Single Image Haze Removal(图像去雾)-CVPR’09 Best Paper

公式推导 paper闪光点 找到了一个很简洁的假设。 paper不足 代码跑起来很慢。据说2010年的ECCV那篇是改进的。

EasyUI学习总结(二)——easyloader分析与使用

使用脚本库总要加载一大堆的样式表和脚本文件&#xff0c;在easyui 中&#xff0c;除了可以使用通常的方式加载之外&#xff0c;还提供了使用 easyloader 加载的方式。这个组件主要是为了按需加载组件而诞生。什么情况下使用它呢&#xff1f; 你觉得一次性导入 easyui 的核心 m…

c语言switch scanf语句,C语言中scanf函数与switch语句

----------------switch----------------1)使用格式switch(表达式){case 常量表达式1: 语句1;case 常量表达式2: 语句2; ...case 常量表达式n: 语句n;default: 语句n1;}判断月份代码实现int main(int argc, const char * argv[]) {//定义变量int month;//提示用户输入一个月份p…

JadClipse eclipse反编译插件

A.下载JadClipse&#xff0c;http://jadclipse.sourceforge.net/wiki/index.php/Main_Page#Download&#xff0c;注意选择与eclipse版本一致的版本&#xff0c;我用的是Eclipse3.4&#xff0c;所以选择下载版本net.sf.jadclipse_3.3.0.jar B.下载Jad&#xff0c;http://www.…

Sublime 资源汇总

2019独角兽企业重金招聘Python工程师标准>>> 《sublime text2使用经验》&#xff1a;里面插件的推介和使用、截图。《Sublime Text 2 入门及技巧》&#xff1a;技巧&#xff0c;可惜是4年前的东西了。《Sublime Text 2安装插件方法详解》&#xff1a;介绍了使用 GoA…

c汇编语言程序框架培训,[010][x86汇编语言]学习用户程序的编写(c08.asm)

源程序来源加载程序c08_mbr.asm用户源程序&#xff1a;增加注释;;文件名&#xff1a;c08-2.asm;文件说明&#xff1a;用户程序;创建日期&#xff1a;13:08 2018/5/23;----------------------------------------------------------------------SECTION header vstart0 ;定义用户…