CoreText的绘制(使用CTFrameDraw直接绘制)
- 简述:通过
NSAttributedString
来绘制富文本 - 流程图:
获取当前context->设置context->设置绘制区域->排版获取CTFrameRef->CTFrameDraw绘制->释放变量
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
//文字相关的属性都是由NSMutableAttributedString来设置的
NSString *theString = @"君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪。人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不复醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。";
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轴的翻转
CGContextScaleCTM(context, 1.0, -1.0);
// 创建绘制区域
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
//排版
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attr);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attr length]), path, NULL);
//整个区域绘制
CTFrameDraw(frame, context);
//释放
CFRelease(frame);
CFRelease(path);
CFRelease(framesetter);
}
使用CTLine一行一行绘制
为什么要一行一行绘制,因为CTFrameDraw
一气呵成的绘制可能导致行高不一致
- (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数组
CFIndex lineCount = CFArrayGetCount(lines);//获取lineRef数组的长度
NSUInteger numberOfLines = lineCount;//默认显示所有文字
CGPoint lineOrigins[numberOfLines];//将每一行起始位置组成一个数组
CTFrameGetLineOrigins(frameRef, CFRangeMake(0, numberOfLines), lineOrigins);
for (CFIndex idx = 0; idx < numberOfLines; idx ++) {//遍历每一行
CGContextRef context = UIGraphicsGetCurrentContext();//获取每一行的上下文
CTLineRef lineRef = CFArrayGetValueAtIndex(lines, idx);//每一行对应的lineRef
CGContextSetTextPosition(context, lineOrigins[idx].x, lineOrigins[idx].y);//设置每一行的起始绘制位置
CTLineDraw(lineRef, context);
}
}
设置行间距
给attr增加一个NSParagraphStyleAttributeName
属性
//设置行间距
CGFloat lineSpacing = 30;
const CFIndex num = 1;
CTParagraphStyleSetting settings[num] = {{kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &lineSpacing}};//数组
CTParagraphStyleRef paragraphRef = CTParagraphStyleCreate(settings, num);
[attr addAttribute:NSParagraphStyleAttributeName value:(__bridge id)(paragraphRef) range:NSMakeRange(0, attr.length)];
//记得释放
CFRelease(paragraphRef);
恩和谐了很多??
将CoreText转化成图片
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
//获取绘制文字的context...
UIImage *screenShotimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
这里UIGraphicsBeginImageContextWithOptions的参数解释如下:第一个表示生成图片的尺寸;第二个参数表示是否透明,0为不透明;第三个参数表示缩放因子,0表示生成图片自动根据屏幕分辨率的变化而变化