TextKit 实现文本分页

TextKit的一些介绍在这里就不多说了,相关的信息可以看这里。这篇文章主要讲文本分页和遇到的问题。
TextKit中主要涉及的就三个类,实现分页也用到这是三个。

NSTextStorage                
NSLayoutManager            
NSTextContainer              

主要的思路就是:

  1. NSTextStorage 存储要分段的文本信息
  2. NSTextStorage 设置 NSLayoutManager
  3. 在NSLayoutManager 中添加 NSTextContainer
  4. 获取NSTextContainer 显示的文本长度
  5. 返回分段信息

这个思路跟CoreText的分段思路差不多,都是获取一定范围内的可见文字的rang,

//TextKit 分页
+ (NSArray *)pagingwithContentString:(NSString *)contentString contentSize:(CGSize)contentSize textAttribute:(NSDictionary *)textAttribute {
    NSMutableArray *pagingArray = [NSMutableArray array];
    NSMutableAttributedString *orginAttString = [[NSMutableAttributedString alloc] initWithString:contentString attributes:textAttribute];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:orginAttString];
    NSLayoutManager* layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    while (YES) {
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:contentSize];
        [layoutManager addTextContainer:textContainer];
        NSRange rang = [layoutManager glyphRangeForTextContainer:textContainer];
        if (rang.length <= 0) {
            break;
        }
        NSString *str = [contentString substringWithRange:rang];
        NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:str attributes:textAttribute];
        [pagingArray addObject:attStr];
    }
    return pagingArray;
}

分页问题解决了,但是在文本渲染的时候却出现了问题。
对于TextView来时,设置富文本有两个方式,一种是通过NSTextStorage设置,一种是直接用attributedText设置,但问题来了同样的NSMutableAttributedString,两种方式渲染出来的效果居然不一样。

左边为attributedText设置,右边为NSTextStorage设置

attributedText设置的行距会比NSTextStorage设置的行距大。这就导致用TextKit分页的结果,用attributedText来设置渲染就会出现显示不全的问题。但是如果文本为英文就没问题。

两边的行距一致

再经过一番研究后发现这是字体造成的,中文如果用<code>[UIFont systemFontOfSize:20]</code>就会出现这种问题,只要换了字体就行了。其中在系统提供的字体中,能够完美使用的有下面几个,

Heiti SC              黑体-简
Heiti TC              黑体-繁
PingFang TC           平方-简
PingFang HK           平方-繁
PingFang SC           平方-繁

</br>
提供一个简单的demo,写的比较简单,不过能说明问题


CoreText分页

下面也提供一下CoreText的分页方法,毕竟CoreText分页的速度会快一点,同样在设置字体的时候,中文内容要用<code>Heiti</code>或<code>PingFang</code>

//CoreText 分页
+ (NSArray *)coreTextPaging:(NSAttributedString *)str textFrame:(CGRect)textFrame{
    NSMutableArray *pagingResult = [NSMutableArray array];
    CFAttributedStringRef cfAttStr = (__bridge CFAttributedStringRef)str;
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(cfAttStr);
    CGPathRef path = CGPathCreateWithRect(textFrame, NULL);

    int textPos = 0; 
    NSUInteger strLength = [str length];
    while (textPos < strLength)  {
        //设置路径
        CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(textPos, 0), path, NULL);
        //生成frame
        CFRange frameRange = CTFrameGetVisibleStringRange(frame);
        NSRange ra = NSMakeRange(frameRange.location, frameRange.length);

       //获取范围并转换为NSRange,然后以NSAttributedString形式保存
        [pagingResult addObject:[str attributedSubstringFromRange:ra]];
        
        //移动当前文本位置
        textPos += frameRange.length;
       
        CFRelease(frame);
    }
    CGPathRelease(path);
    CFRelease(framesetter);
    return pagingResult;
}

简单的demo:demo地址

推荐阅读更多精彩内容

  • 转载:https://yq.aliyun.com/articles/60173 https://objccn.io...
    F麦子阅读 1,463评论 0 1
  • 厦门路小学四年级三班宿琳棋爸爸 今天是传统的七夕节,带着儿子回家看望父母。刚一进门就看到父亲在菜园干活,我立刻下手...
    宿孟豹阅读 29评论 0 0
  • 江山伴画淡定坐, 雏凤亮丽唱中国 。 注 春华秋实卅载情, 一带一路万里歌。 ——《青年女歌手》(油画:靳尚谊) ...
    珠江潮平阅读 198评论 47 38
  • 居延遗址分布在今内蒙古自治区额济纳旗和甘肃省金塔县的境内。指的是包括汉代张掖郡居延、肩水两都尉所辖边塞上的...
    塞外苍鹰阅读 366评论 0 1