TextKit 实现文本分页

作者: XPorter | 来源:发表于2016-08-18 10:55 被阅读1321次

    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地址

    相关文章

      网友评论

        本文标题:TextKit 实现文本分页

        本文链接:https://www.haomeiwen.com/subject/brrvsttx.html