在iOS上使用TextKit进行文本分页

Textkit的框架

对于显示在视图上的字符串,它需要经历几个过程:存储字符串->排版->显示。

TextStorage类是用于存储字符串的容器,因此首先必须将字符串(无论是纯文本还是富文本格式)打包到TextStorage中 ,然后LayoutManager将管理文本的布局,之后是TextContainer类将控制位置和页面大小,请注意TextContainerTextView的大小均不正确,这将在本文后面提到。

设置完所有内容后,您可以使用UITextViewUILabel在视图上显示文本。 在实际开发中,我的建议是在某些尺寸问题的情况下使用TextView

分页

使用TextKit进行分页非常简单。 根据Apple的官方文档,LayoutManager和TextContainer可以一起完成分页工作,同时,如果您有其他要求,则需要一种算法。

从上图中, LayoutManagerTextStorage读取字符串,并根据添加到LayoutManagerTextContainer的数量执行页面布局。

如果只有一个TextContainer ,则将仅排版第一页的数据,而另一页将被丢弃。 如果有多个TextContainer ,则可以完成大文本分页。

  // 1. 从文件中读取字符串。 
NSString * textString = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@“ Text” ofType:@“ txt”]编码:NSUTF8StringEncoding错误:无];

// 2. 将字符串打包到存储中。
NSTextStorage *存储= [[NSTextStorage alloc] initWithString:textString];

// 3. 为存储添加布局管理。
NSLayoutManager * layoutManager = [[NSLayoutManager alloc] init];
[存储addLayoutManager:layoutManager];

同时(是)
{
// 4. 将具有确定大小的TextContainer添加到LayoutManager
NSTextContainer * textContainer = [[[NSTextContainer alloc] initWithSize:CGSizeMake(sTextViewWidth,sTextViewHeight)]];
[layoutManager addTextContainer:textContainer];

// 5. 将TextContainer绑定到TextView
UITextView * textView = [[UITextView alloc] initWithFrame:CGRectMake(0,0,sTextViewWidth,sTextViewHeight)textContainer:textContainer];
textView.editable = NO;
[scrollView addSubview:textView];
  i ++; 
  // 6. 排版的确定。 
NSRange range = [layoutManager glyphRangeForTextContainer:textContainer];
如果(range.length + range.location == textString.length)
打破;
}

PS“ sTextViewWidth”和“ sTextViewHeight”是Textview的高度和宽度宏。

有一些用于LayoutManager的排版计算的常用方法。

  -(NSRange)glyphRangeForTextContainer:(NSTextContainer *)容器; 
-(NSRange)glyphRangeForBoundingRect:(CGRect)bounds inTextContainer:(NSTextContainer *)container;
-(CGRect)usedRectForTextContainer:(NSTextContainer *)容器;

最后

Apple不提供反向排版。 因此,如果您需要计算前一页数据,请自行设计一个合适的算法。

问题

在普通文本中找不到此问题,但是在富文本中出现了此问题,具体情况是,当将TextContainerTextView的大小设置为相同时,最终的显示结果并不完美:页面的几乎所有末端都是不规则的,即使单词的最后一行也将被剪掉一半。

这是我的解决方案:

  1. 确保TextContainer的大小。 高度比TextView短一行。
  2. 请小心控制TextView的框架,以使上下边框的值尽可能相等。