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ù)屏幕分辨率的變化而變化