coreText绘制文本

coreText绘制文本

    我们需要知道我们是将用Coretext布局好的文本图片信息绘制在view上,并在view的drawRect方法。现在我们先初步了解一下步骤:

  • 首先,我们需要根据要显示的文本以及文本属性初始化一个NSMutableAttributedString;
  • 根据文本以及文本属性配置CTFramesetterRef;
  • 设置绘制区域(CGPathRef),并根据绘制区域和CTFramesetterRef生成CTFrameRef;
  • 最后将排版好的文本绘制到view上。

    为了使代码结构清晰,可以将配置文本属性(包括字体大小,行间距等信息)写成一个类,再用一个类去排版布局文本,最后将排版好的文本绘制在view上。

  1. 首先根据要显示的文本以及文本属性生成NSMutableAttributedString
       //content就是要显示的文本内容
       NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:content];
        //config是用来记录文本属性(包括字体大小,字体颜色等信息)的类的对象
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        //记录字体大小
        dict[NSFontAttributeName] = [UIFont systemFontOfSize:config.fontSize];
        //字体颜色
        dict[NSForegroundColorAttributeName] = config.fontColor;
        //行间距
        NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
        style.lineSpacing = config.lineSpace;
        style.alignment = NSTextAlignmentJustified;
        dict[NSParagraphStyleAttributeName] = style;
        //设置属性以及文本内容(也可以分别设置字体大小,字体颜色等属性)
        [attString addAttributes:dict range:NSMakeRange(0, content.length)];
        //两个参数分别是文本属性、该文本属性约束的文本范围
        //这里将整个文本(NSMakeRange(0, content.length))设置成了同一种样式,我们也可以根据自己的需求分别设置每一段的字体样式,也可以加下划线,字体加粗等。
  2. 根据文本以及文本属性配置CTFramesetterRef
    CTFramesetterRef setterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);

    注:这里需要将OC对象转为CF对象,__bridge表示在将OC对象转为CF对象时不涉及对象转换,所以转换后不需要手动释放attString  

  3. 设置绘制区域,并根据绘制区域和CTFramesetterRef生成CTFrameRef
        //文本要布局显示的区域
        CGPathRef pathRef = CGPathCreateWithRect(bounds, NULL);
        //将CFRangeMake(0, 0)length设为0布局会根据CTFramesetterRef在pathRef区域内一直排版直到排满
        CTFrameRef frameRef = CTFramesetterCreateFrame(setterRef, CFRangeMake(0, 0), pathRef, NULL);
        //第一个参数是待排版的CTFramesetterRef,第二个参数是排版的文字范围,第三个参数是排版区域。
        CFRelease(setterRef);
        CFRelease(pathRef);

    注:ARC环境下编译器不会自动管理CF对象的内存,需要手动释放

  4. 以上内容写在一个用于排版的类(生成CTFrameRef)中,通过这个类获取到 CTFrameRef后,在view里重写drawRect方法,将布局好的文本绘制到view上
  5. - (void)drawRect:(CGRect)rect{
        if (!_frameRef) {//在view中声明了一个CTFrameRef
            return;
        }
        //翻转坐标系
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
        CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        //绘制到view
        CTFrameDraw(_frameRef, ctx);
    }

    注:CoreText坐标系和UIKit坐标系的不同,绘制之前我们需要将坐标系统一; _frameRef不会自动释放,我们必须要手动释放掉。

    -(void)setFrameRef:(CTFrameRef)frameRef{
        if (_frameRef != frameRef) {
            if (_frameRef) {     //释放_frameRef
                CFRelease(_frameRef);
                _frameRef = nil;
            }
            _frameRef = frameRef;
        }
    }
    -(void)dealloc
    {
        if (_frameRef) {
            CFRelease(_frameRef);
            _frameRef = nil;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_39696600/article/details/81324116