很碍眼的黄色警告标志。
先来看看iOS7 SDK包中关于boudingRectWithSize:options:attributes:context方法的定义:
- // NOTE: All of the following methods will default to drawing on a baseline, limiting drawing to a single line.
- // To correctly draw and size multi-line text, pass NSStringDrawingUsesLineFragmentOrigin in the options parameter.
- @interface NSString (NSExtendedStringDrawing)
- - (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);
- - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);
- @end
关于该方法,NSAttributedString其实也有一个同名的方法:
- @interface NSAttributedString (NSExtendedStringDrawing)
- - (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- @end
- typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
- 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.
- NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
- NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
- NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
- } NS_ENUM_AVAILABLE_IOS(6_0);
- NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:textView.text];
- textView.attributedText = attrStr;
- NSRange range = NSMakeRange(0, attrStr.length);
- NSDictionary *dic = [attrStr attributesAtIndex:0 effectiveRange:&range]; // 获取该段attributedString的属性字典
- // 计算文本的大小
- CGSize textSize = [textView.text boundingRectWithSize:textView.bounds.size // 用于计算文本绘制时占据的矩形块
- options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading // 文本绘制时的附加选项
- attributes:dic // 文字的属性
- context:nil].size; // context上下文。包括一些信息,例如如何调整字间距以及缩放。该对象包含的信息将用于文本绘制。该参数可为nil
- NSLog(@"w = %f", textSize.width);
- NSLog(@"h = %f", textSize.height);
- NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
- 2013-09-02 21:04:47.470 BoudingRect_i7_Demo[3532:a0b] w = 322.171875
- 2013-09-02 21:04:47.471 BoudingRect_i7_Demo[3532:a0b] h = 138.000015
- NSStringDrawingUsesLineFragmentOrigin // The specified origin is the line fragment origin, not the base line origin
- 2013-09-02 17:35:40.547 BoudingRect_i7_Demo[1871:a0b] w = 318.398438
- 2013-09-02 17:35:40.549 BoudingRect_i7_Demo[1871:a0b] h = 69.000000
- 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.
- 2013-09-02 17:37:38.398 BoudingRect_i7_Demo[1902:a0b] w = 1523.408203
- 2013-09-02 17:37:38.400 BoudingRect_i7_Demo[1902:a0b] h = 13.800000
- NSStringDrawingUsesFontLeading // Uses the font leading for calculating line heights
- 2013-09-02 17:40:45.903 BoudingRect_i7_Demo[1932:a0b] w = 1523.408203
- 2013-09-02 17:40:45.905 BoudingRect_i7_Demo[1932:a0b] h = 13.800000
- NSStringDrawingUsesDeviceMetrics // Uses image glyph bounds instead of typographic bounds
- 2013-09-02 17:42:03.283 BoudingRect_i7_Demo[1956:a0b] w = 1523.408203
- 2013-09-02 17:42:03.284 BoudingRect_i7_Demo[1956:a0b] h = 13.800000
如果为NSStringDrawingTruncatesLastVisibleLine或者NSStringDrawingUsesDeviceMetric,那么计算文本尺寸时将以每个字或字形为单位来计算。
- /* 判断是否需要分页和进行分页动作 */
- -(BOOL)paging
- {
- /* 获取Settings中设定好的字体(主要是获取字体大小) */
- static const CGFloat textScaleFactor = 1.; // 设置文字比例
- NSString *textStyle = [curPageView.textView tkd_textStyle]; // 设置文字样式
- preferredFont_ = [UIFont tkd_preferredFontWithTextStyle:textStyle scale:textScaleFactor]; //设置prferredFont(包括样式和大小)
- NSLog(@"paging: %@", preferredFont_.fontDescriptor.fontAttributes); // 在控制台中输出字体的属性字典
- /* 设定每页的页面尺寸 */
- NSUInteger height = (int)self.view.bounds.size.height - 40.0; // 页面的高度
- /* 获取文本的总尺寸 */
- NSDictionary *dic = preferredFont_.fontDescriptor.fontAttributes;
- CGSize totalTextSize = [bookItem.content.string boundingRectWithSize:curPageView.textView.bounds.size
- options:NSStringDrawingUsesLineFragmentOrigin
- attributes:dic
- context:nil].size;
- NSLog(@"w = %f", totalTextSize.width);
- NSLog(@"h = %f", totalTextSize.height);
- /* 开始分页 */
- if (totalTextSize.height < height) {
- /* 如果一页就能显示完,直接显示所有文本 */
- totalPages_ = 1; // 设定总页数为1
- charsPerPage_ = [bookItem.content length]; // 设定每页的字符数
- textLength_ = [bookItem.content length]; // 设定文本总长度
- return NO; // 不用分页
- }
- else {
- /* 计算理想状态下的页面数量和每页所显示的字符数量,用来作为参考值用 */
- textLength_ = [bookItem.content length]; // 文本的总长度
- NSUInteger referTotalPages = (int)totalTextSize.height / (int)height + 1; // 理想状态下的总页数
- NSUInteger referCharactersPerPage = textLength_ / referTotalPages; // 理想状态下每页的字符数
- // 输出理想状态下的参数信息
- NSLog(@"textLength = %d", textLength_);
- NSLog(@"referTotalPages = %d", referTotalPages);
- NSLog(@"referCharactersPerPage = %d", referCharactersPerPage);
- /* 根据referCharactersPerPage和text view的高度开始动态调整每页的字符数 */
- // 如果referCharactersPerPage过大,则直接调整至下限值,减少调整的时间
- if (referCharactersPerPage > 1000) {
- referCharactersPerPage = 1000;
- }
- // 获取理想状态下的每页文本的范围和pageText及其尺寸
- NSRange range = NSMakeRange(referCharactersPerPage, referCharactersPerPage); // 一般第一页字符数较少,所以取第二页的文本范围作为调整的参考标准
- NSString *pageText = [bookItem.content.string substringWithRange:range]; // 获取该范围内的文本
- NSLog(@"%@", pageText);
- NSRange ptrange = NSMakeRange(0, pageText.length);
- NSDictionary *ptdic = [[bookItem.content attributedSubstringFromRange:ptrange] attributesAtIndex:0 effectiveRange:&ptrange];
- CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
- options:NSStringDrawingUsesLineFragmentOrigin
- attributes:ptdic
- context:nil].size;
- // 若pageText超出text view的显示范围,则调整referCharactersPerPage
- NSLog(@"height = %d", height);
- while (pageTextSize.height > height) {
- NSLog(@"pageTextSize.height = %f", pageTextSize.height);
- referCharactersPerPage -= 2; // 每页字符数减2
- range = NSMakeRange(0, referCharactersPerPage); // 重置每页字符的范围
- ptdic = [[bookItem.content attributedSubstringFromRange:range] attributesAtIndex:0 effectiveRange:&range];
- CGSize pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
- options:NSStringDrawingUsesLineFragmentOrigin
- attributes:ptdic
- context:nil].size;
- pageText = [bookItem.content.string substringWithRange:range]; // 重置pageText
- pageTextSize = [pageText boundingRectWithSize:curPageView.textView.bounds.size
- options:NSStringDrawingUsesLineFragmentOrigin
- attributes:ptdic
- context:nil].size; // 获取pageText的尺寸
- }
- // 根据调整后的referCharactersPerPage设定好charsPerPage_
- charsPerPage_ = referCharactersPerPage;
- NSLog(@"cpp: %d", charsPerPage_);
- // 计算totalPages_
- totalPages_ = (int)bookItem.content.length / charsPerPage_ + 1;
- NSLog(@"ttp: %d", totalPages_);
- // 计算最后一页的字符数,防止范围溢出
- charsOfLastPage_ = textLength_ - (totalPages_ - 1) * charsPerPage_;
- NSLog(@"colp: %d", charsOfLastPage_);
- // 分页完成
- return YES;
- }
- }
这样就看不到碍眼的黄色警告标志了。
重要的是,由于该方法计算文本的尺寸更为准确,所以可以使得分页后页与页之间的连贯性好了很多,而且每页的空间利用率都提高了很多,每页的文字几乎铺满了整个页面。