CoreText繪制富文本

CoreText的繪制(使用CTFrameDraw直接繪制)

  • 簡述:通過NSAttributedString來繪制富文本
  • 流程圖:
    獲取當(dāng)前context->設(shè)置context->設(shè)置繪制區(qū)域->排版獲取CTFrameRef->CTFrameDraw繪制->釋放變量
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    //文字相關(guān)的屬性都是由NSMutableAttributedString來設(shè)置的
    NSString *theString = @"君不見,黃河之水天上來,奔流到海不復(fù)回。君不見,高堂明鏡悲白發(fā),朝如青絲暮成雪。人生得意須盡歡,莫使金樽空對月。天生我材必有用,千金散盡還復(fù)來。烹羊宰牛且為樂,會須一飲三百杯。岑夫子,丹丘生,將進(jìn)酒,杯莫停。與君歌一曲,請君為我傾耳聽。鐘鼓饌玉不足貴,但愿長醉不復(fù)醒。古來圣賢皆寂寞,惟有飲者留其名。陳王昔時宴平樂,斗酒十千恣歡謔。主人何為言少錢,徑須沽取對君酌。五花馬,千金裘,呼兒將出換美酒,與爾同銷萬古愁。";
    NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:theString];
    [attr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:25] range:NSMakeRange(4, 5)];
    [attr addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:20] range:NSMakeRange(11, 4)];
    [attr addAttribute:NSForegroundColorAttributeName value:[UIColor purpleColor] range:NSMakeRange(3, 4)];
    
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    //向上平移一個視圖高度的距離
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    //圍繞x軸的翻轉(zhuǎn)
    CGContextScaleCTM(context, 1.0, -1.0);
  
    // 創(chuàng)建繪制區(qū)域
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, self.bounds);
    
    //排版
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attr);
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attr length]), path, NULL);
    
    //整個區(qū)域繪制
    CTFrameDraw(frame, context);
    
    //釋放
    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
}
image.png

使用CTLine一行一行繪制

為什么要一行一行繪制,因為CTFrameDraw一氣呵成的繪制可能導(dǎo)致行高不一致

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    //同上...

    //一行一行繪制
    [self _drawText:frame];

    //釋放
    CFRelease(paragraphRef);
    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
}

/**
 一行一行的寫字
 */
- (void)_drawText:(CTFrameRef)frameRef{
    CFArrayRef lines = CTFrameGetLines(frameRef);//獲取lineRef數(shù)組
    CFIndex lineCount = CFArrayGetCount(lines);//獲取lineRef數(shù)組的長度
    NSUInteger numberOfLines = lineCount;//默認(rèn)顯示所有文字
    CGPoint lineOrigins[numberOfLines];//將每一行起始位置組成一個數(shù)組
    CTFrameGetLineOrigins(frameRef, CFRangeMake(0, numberOfLines), lineOrigins);
    for (CFIndex idx = 0; idx < numberOfLines; idx ++) {//遍歷每一行
        CGContextRef context = UIGraphicsGetCurrentContext();//獲取每一行的上下文
        CTLineRef lineRef = CFArrayGetValueAtIndex(lines, idx);//每一行對應(yīng)的lineRef
        CGContextSetTextPosition(context, lineOrigins[idx].x, lineOrigins[idx].y);//設(shè)置每一行的起始繪制位置
        CTLineDraw(lineRef, context);
    }
}
image.png

設(shè)置行間距

給attr增加一個NSParagraphStyleAttributeName屬性

   //設(shè)置行間距
    CGFloat lineSpacing = 30;
    const CFIndex num = 1;
    CTParagraphStyleSetting settings[num] = {{kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &lineSpacing}};//數(shù)組
    CTParagraphStyleRef paragraphRef = CTParagraphStyleCreate(settings, num);
    [attr addAttribute:NSParagraphStyleAttributeName value:(__bridge id)(paragraphRef) range:NSMakeRange(0, attr.length)];

    //記得釋放
    CFRelease(paragraphRef);

image.png

恩和諧了很多??

將CoreText轉(zhuǎn)化成圖片

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);

    //獲取繪制文字的context...
    
    UIImage *screenShotimage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

這里UIGraphicsBeginImageContextWithOptions的參數(shù)解釋如下:第一個表示生成圖片的尺寸;第二個參數(shù)表示是否透明,0為不透明;第三個參數(shù)表示縮放因子,0表示生成圖片自動根據(jù)屏幕分辨率的變化而變化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容