CoreText 学习笔记 一
来源:互联网 发布:郑大网络教育 编辑:程序博客网 时间:2024/04/29 03:34
CoreText 坐标系是以左下角为坐标原点。而我们经常使用的uikit是以左上角为坐标原点,因此 CoreText 中的布局完成后需要对其进行坐标系转换
一般做法: 获取当前上下文,将当前上下文坐标转换成CT坐标系,再将布局好的CT绘制到当前上下文即可
//获取当前上下文 CGContextRef context = UIGraphicsGetCurrentContext(); //翻转坐标系步骤 //设置当前文本矩阵 CGContextSetTextMatrix(context, CGAffineTransformIdentity); //文本沿y轴移动 CGContextTranslateCTM(context, 0, self.bounds.size.height); //文本翻转成为CoreText坐标系 CGContextScaleCTM(context, 1, -1);
CoreText文本布局
1.首先要确定布局时绘制的区域,其对应的类为CG(Mutable)PathRef
2.设置文本内容,其对应的类为NS(Mutable)AttributedString
3.根据文本内容配置其CTFramesetterRef
4.利用CTFramesetterRef得到CTFrame
//1.创建绘制区域,显示的区域可以用CGMUtablePathRef生成任意的形状 CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, CGRectMake(20, 50, self.bounds.size.width - 40, self.bounds.size.height - 100)); //2.创建需要绘制的文字 NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"\tWhen I will learn CoreText, i think it will hard for me.But it is easy.\n\tIn fact,if you bengin learn, you can know that every thing is easy when you start.you just need some knowlages"]; //3.根据AttString生成CTFramesetterRef CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString); CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attString length]), path, NULL);
文本属性设置
//设置绘制的文本内容 NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"\tWhen I will learn CoreText, i think it will hard for me.But it is easy.\n\tIn fact,if you bengin learn, you can know that every thing is easy when you start.you just need some knowlages"]; //设置文本内容的属性 //1设置部分文字颜色 [attString addAttribute:(id)kCTForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0 , 27)]; //2设置部分文字字体 CGFloat fontSize = 20; CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL); [attString addAttribute:(id)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0, 27)]; //3设置斜体 CTFontRef italicFontRef = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 16, NULL); [attString addAttribute:(id)kCTFontAttributeName value:(__bridge id)italicFontRef range:NSMakeRange(27, 9)]; //4设置下划线 [attString addAttribute:(id)kCTUnderlineStyleAttributeName value:(id)[NSNumber numberWithInteger:kCTUnderlineStyleDouble] range:NSMakeRange(36, 10)]; //5设置下划线颜色 [attString addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[UIColor greenColor].CGColor range:NSMakeRange(36, 10)]; //6设置空心字 long number1 = 2; CFNumberRef numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &number1); [attString addAttribute:(id)kCTStrokeWidthAttributeName value:(__bridge id)numRef range:NSMakeRange(56, 10)]; //7设置字体间距 long number = 10; CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &number); [attString addAttribute:(id)kCTKernAttributeName value:(__bridge id)num range:NSMakeRange(40, 10)]; //8设置行间距 CGFloat lineSpacing = 10; const CFIndex kNumberOfSettings = 3; CTParagraphStyleSetting theSettings[kNumberOfSettings] = { {kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &lineSpacing}, {kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(CGFloat), &lineSpacing}, {kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(CGFloat), &lineSpacing} }; CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings); [attString addAttribute:(id)kCTParagraphStyleAttributeName value:(__bridge id)theParagraphRef range:NSMakeRange(0, [attString length])];
图片文本内容
图片宽高在工程中都需要加载后才知道,而在文本绘制中需要直接留出其位置再进行绘制,所以图片的宽高都是在数据中保存好的,此处笔者用固定值来表示其宽高。为了留出其位置我们需要用空白的字符来做占位符使用。为了知道其图片绘制的位置(即空白占位符位置)我们需要设置代理才能够得知图片绘制位置。具体步骤如下:
1.创建CTRunDelegateCallbacks 回调函数:通过回调函数来确定图片绘制的宽高
2.创建空白占位字符
3.设置CTRunDeleagte:通过代理来找到该字符串,并确定图片绘制的原点
#pragma mark - CTRunDelegateCallbacks Method//此处使用的字典结构来存储数值static CGFloat heightCallBack(void *ref) { return [(NSNumber *)[(__bridge NSDictionary *)ref objectForKey:@"height"] floatValue];}static CGFloat descentCallBack (void *ref) { return 0;}static CGFloat widthCallBack (void *ref) { return [(NSNumber *)[(__bridge NSDictionary *)ref objectForKey:@"width"] floatValue];}
#pragma mark - 空白占位符及代理设置
//CTRunDelegateCallBacks:用于保存指针的结构体,由CTRun delegate进行回调 CTRunDelegateCallbacks callbacks; memset(&callbacks, 0, sizeof(CTRunDelegateCallbacks)); callbacks.version = kCTRunDelegateVersion1; callbacks.getAscent = heightCallBack; callbacks.getDescent = descentCallBack; callbacks.getWidth = widthCallBack; //图片信息字典 NSDictionary *imgInfoDic = @{@"width":@320,@"height":@230}; //创建CTRunDelegate的代理 CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, (__bridge void*)imgInfoDic); //使用oxFFFC作为空白占位符 unichar objectReplacementChar = 0xFFFC; NSString *content = [NSString stringWithCharacters:&objectReplacementChar length:1]; NSMutableAttributedString *space = [[NSMutableAttributedString alloc] initWithString:content]; //设置代理 CFAttributedStringSetAttribute((CFMutableAttributedStringRef)space, CFRangeMake(0, 1), kCTRunDelegateAttributeName, delegate);
在贴出获取图片位置代码前,还需要补充一个理论知识,在CoreText中所有的布局都是基于行(CTLineRef)来进行的,每行都是一个CTLineRef对象,在每行当中又包含多个属性(CTRunRef)每行的属性可设置代理,如上面笔者就是对空白占位符这个CTRunRef设置了代理。下面为CTLineRef和CTRunRef的示意图
具体代码:
//获取CTLine数组 NSArray *lines = (NSArray *)CTFrameGetLines(ctframe); NSInteger lineCount = lines.count; CGPoint lineOrigins[lineCount]; CTFrameGetLineOrigins(ctframe, CFRangeMake(0, 0), lineOrigins); //遍历每一个CTline for (NSInteger i = 0; i < lineCount; i ++) { CTLineRef line = (__bridge CTLineRef)lines[i]; NSArray *runObjArray = (NSArray *)CTLineGetGlyphRuns(line); //遍历每个CTLine中的CTRun找到空白字符的delegate for (id runObj in runObjArray) { CTRunRef run = (__bridge CTRunRef)runObj; NSDictionary *runAttributes = (NSDictionary *)CTRunGetAttributes(run); CTRunDelegateRef delegate = (__bridge CTRunDelegateRef)[runAttributes valueForKey:(id)kCTRunDelegateAttributeName]; if (delegate == nil) { continue; } NSDictionary *metaDic = CTRunDelegateGetRefCon(delegate); if (![metaDic isKindOfClass:[NSDictionary class]]) { continue; } //找到代理后开始计算空白字符的位置 CGRect runBounds; CGFloat ascent; CGFloat descent; runBounds.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL); runBounds.size.height = ascent + descent; //计算在行当中的x偏移量 CGFloat xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL); runBounds.origin.x = lineOrigins[i].x + xOffset; runBounds.origin.y = lineOrigins[i].y - descent; //获得ctframe的绘制区域 CGPathRef pathRef = CTFrameGetPath(ctframe); //计算此绘制区域的范围 CGRect colRect = CGPathGetBoundingBox(pathRef); //计算在此区域中空白字符的位置 CGRect delegateBounds= CGRectOffset(runBounds, colRect.origin.x, colRect.origin.y); //记录空白字符位置 _imageRect = delegateBounds; //返回空白字符位置 return delegateBounds; } }//若没有找到对应的代理则返回空位置return CGRectZero;
绘制文本内容
//绘制文本 CTFrameDraw(frame, context); //绘制图像 UIImage *image = [UIImage imageNamed:@"boat.jpg"]; CGContextDrawImage(context, _imageRect, image.CGImage);
0 0
- CoreText 学习笔记 一
- CoreText 学习笔记
- 【IOS学习】CoreText学习笔记(一)相关的类
- [iOS]CoreText 学习笔记(1)
- CoreText笔记
- CoreText笔记
- CoreText学习(一)Base Objects of Core Text
- CoreText学习(一)Base Objects of Core Text
- CoreText学习记录一:筛选网址显示不同颜色+Demo+pdf
- CoreText(一):基本用法
- IOS CoreText系列一:理论
- 【IOS学习】CoreText学习笔记(二)设置文字属性和插入图片
- coretext
- CoreText
- coretext
- coreText
- coreText
- coretext
- 解决Flex4 发布后访问 初始化极其缓慢的问题
- Xcode打包上传报错“ All object files and libraries for bitcode must be generated from Xcode Archive or Ins”
- wwWFrank2的Android学习之路准备阶段
- 设计模式--工厂模式--徐旸
- WINDOWS下BOOST库编译
- CoreText 学习笔记 一
- 车架号扫描识别SDK
- 键盘监听事件
- nexus6 刷 安卓6.0.1 root 装xposed 并配置手机
- 欢迎使用CSDN-markdown编辑器
- java 学习笔记--利用反射实现自定义toString()的工具类
- JavaScript解析json字符串
- Tcpdump 的用法
- Qt5.7编译oracle数据库驱动(提供下载)