NSString *str = @"This is a test of characterAttribute. 中文字符";
NSMutableAttributedString *mabstring = [[NSMutableAttributedString alloc]initWithString:str];
[mabstring beginEditing];
//some code
[mabstring endEditing];
//CTFramesetter是CTFrame的创建工厂,NSAttributedString需要通过CTFrame绘制到界面上,得到CTFramesetter后,创建path(绘制路径),然后得到CTFrame,最后通过CTFrameDraw方法绘制到界面上
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mabstring);
CGMutablePathRef Path = CGPathCreateMutable();
CGPathAddRect(Path, NULL ,CGRectMake(10 , -20 ,self.bounds.size.width-10 , self.bounds.size.height-10));
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);
//获取当前(View)上下文以便于之后的绘画,这个是一个离屏。
CGContextRef context = UIGraphicsGetCurrentContext();
// 调整坐标系,防止文字倒立。
CGContextSetTextMatrix(context , CGAffineTransformIdentity);
//压栈,压入图形状态栈中.每个图形上下文维护一个图形状态栈,并不是所有的当前绘画环境的图形状态的元素都被保存。图形状态中不考虑当前路径,所以不保存
//保存现在得上下文图形状态。不管后续对context上绘制什么都不会影响真正得屏幕。
CGContextSaveGState(context);
//x,y轴方向移动
CGContextTranslateCTM(context , 0 ,self.bounds.size.height);
//缩放x,y轴方向缩放,-1.0为反向1.0倍,坐标系转换,沿x轴翻转180度
CGContextScaleCTM(context, 1.0 ,-1.0);
CTFrameDraw(frame,context);
CGPathRelease(Path);
CFRelease(framesetter);
定制text
//设置字体间隔
//const CFStringRef kCTKernAttributeName;//字符间隔属性,必须是CFNumberRef对象
//设置字体间隔
long number = 10;
CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);
[mabstring addAttribute:(id)kCTKernAttributeName value:(__bridge id)num range:NSMakeRange(0, 5)];
//设置字体属性 Georgia
//const CFStringRef kCTFontAttributeName;//字体 CTFont Default is Helvetica 12. 与UIFont的默认值不同
CTFontRef font = CTFontCreateWithName(CFSTR("Zapfino"), 40, NULL);
[mabstring addAttribute:(id)kCTFontAttributeName value:(__bridge id)font range:NSMakeRange(0, 4)];
//设置字体颜色 kCTForegroundColorAttributeName
[mabstring addAttribute:(id)kCTForegroundColorAttributeName value:(id)[UIColor yellowColor].CGColor range:NSMakeRange(0, 9)];
//设置字体颜色为前影色
CFBooleanRef flag = kCFBooleanTrue;
[mabstring addAttribute:(id)kCTForegroundColorFromContextAttributeName value:(__bridge id)flag range:NSMakeRange(5, 10)];
//设置空心字
number = 2;
CFNumberRef num2 = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);
[mabstring addAttribute:(id)kCTStrokeWidthAttributeName value:(__bridge id)num2 range:NSMakeRange(0, [str length])];
//设置空心字颜色
[mabstring addAttribute:(id)kCTStrokeColorAttributeName value:(id)[UIColor greenColor].CGColor range:NSMakeRange(0, [str length])];
//设置斜体字
CTFontRef font1 = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 14, NULL);
[mabstring addAttribute:(id)kCTFontAttributeName value:(__bridge id)font1 range:NSMakeRange(0, 4)];
//下划线
[mabstring addAttribute:(id)kCTUnderlineStyleAttributeName value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] range:NSMakeRange(0, 4)];
//下划线颜色
[mabstring addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(0, 4)];
同时设置多个属性
//对同一段字体进行多属性设置
//红色
NSMutableDictionary *attributesDict = [NSMutableDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(id)kCTForegroundColorAttributeName];
//斜体
//创建字体以及字体大小
CTFontRef font = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 40, NULL);
[attributesDict setObject:(__bridge id)font forKey:(id)kCTFontAttributeName];
//下划线
[attributesDict setObject:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble] forKey:(id)kCTUnderlineStyleAttributeName];
//空心字
long number = 5;
CFNumberRef num2 = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);
[attributesDict setObject:(__bridge id)num2 forKey:(id)kCTStrokeWidthAttributeName];
[mabstring addAttributes:attributesDict range:NSMakeRange(0, 4)];
添加段落属性
//段落
//line break
CTParagraphStyleSetting lineBreakMode;
CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping; //换行模式
lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
lineBreakMode.value = &lineBreak;
lineBreakMode.valueSize = sizeof(CTLineBreakMode);
//行间距
CTParagraphStyleSetting LineSpacing;
CGFloat spacing = 40.0; //指定间距
LineSpacing.spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;
LineSpacing.value = &spacing;
LineSpacing.valueSize = sizeof(CGFloat);
CTParagraphStyleSetting settings[] = {lineBreakMode,LineSpacing};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, 2); //第二个参数为settings的长度
[mabstring addAttribute:(NSString *)kCTParagraphStyleAttributeName
value:(__bridge id)paragraphStyle
range:NSMakeRange(0, mabstring.length)];
分列
// get current context and store it's state
//创建图形上下文
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// translate CTM for iOS
//重置位置
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1, -1);
// generate attributed string
NSAttributedString *attrString = [[NSAttributedString alloc]initWithString:@"这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890,这是测试1234567890"];
// Draw code start -------------------------------------------------------------------------------------------------
CGRect bounds = CGRectInset(self.bounds, 25.0f, 25.0f);
float columnWidth = (bounds.size.width - 30.0f) / 2.0f;
float columnHeight = bounds.size.height;
CTFramesetterRef framesetter
= CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attrString));
int location = 0;
// ------------- first column
CGRect firstColumnRect = CGRectMake(bounds.origin.x, bounds.origin.y, columnWidth, columnHeight);
CGMutablePathRef firstColumnPath = CGPathCreateMutable();
CGPathAddRect(firstColumnPath, NULL, firstColumnRect);
CTFrameRef firstColumnFrame =
CTFramesetterCreateFrame(framesetter, CFRangeMake(location, 0), firstColumnPath, NULL);
//计算指定frame绘制了多少字符
CFRange firstColumnStringRange = CTFrameGetVisibleStringRange(firstColumnFrame);
CTFrameDraw(firstColumnFrame, context);
// recalculate the location for next frame.
location = firstColumnStringRange.length;
// ------------- second column
CGRect secondColumnRect =
CGRectMake(bounds.origin.x + 30 + columnWidth, bounds.origin.y, columnWidth, columnHeight);
CGMutablePathRef secondColumnPath = CGPathCreateMutable();
CGPathAddRect(secondColumnPath, NULL, secondColumnRect);
CTFrameRef secondColumnFrame =
CTFramesetterCreateFrame(framesetter,
CFRangeMake(location, 0),
secondColumnPath, NULL);
CTFrameDraw(secondColumnFrame, context);
// release
CFRelease(firstColumnPath);
CFRelease(firstColumnFrame);
CFRelease(secondColumnPath);
CFRelease(secondColumnFrame);
CFRelease(framesetter);
// Draw code end -------------------------------------------------------------------------------------------------
// restore current context
CGContextRestoreGState(context);
段落样式
NSMutableAttributedString * mabstring = [[NSMutableAttributedString alloc]initWithString:src];
long slen = [mabstring length];
/*
对齐属性:
kCTLeftTextAlignment = 0, //左对齐
kCTRightTextAlignment = 1, //右对齐
kCTCenterTextAlignment = 2, //居中对齐
kCTJustifiedTextAlignment = 3, //文本对齐
kCTNaturalTextAlignment = 4 //自然文本对齐
段落默认样式为
kCTNaturalTextAlignment
*/
//创建文本对齐方式
CTTextAlignment alignment = kCTNaturalTextAlignment;//kCTNaturalTextAlignment;
CTParagraphStyleSetting alignmentStyle;
alignmentStyle.spec=kCTParagraphStyleSpecifierAlignment;//指定为对齐属性
alignmentStyle.valueSize=sizeof(alignment);
alignmentStyle.value=&alignment;
//首行缩进
CGFloat fristlineindent = 24.0f;
CTParagraphStyleSetting fristline;
fristline.spec = kCTParagraphStyleSpecifierFirstLineHeadIndent;
fristline.value = &fristlineindent;
fristline.valueSize = sizeof(float);
//段缩进
CGFloat headindent = 10.0f;
CTParagraphStyleSetting head;
head.spec = kCTParagraphStyleSpecifierHeadIndent;
head.value = &headindent;
head.valueSize = sizeof(float);
//段尾缩进
CGFloat tailindent = 50.0f;
CTParagraphStyleSetting tail;
tail.spec = kCTParagraphStyleSpecifierTailIndent;
tail.value = &tailindent;
tail.valueSize = sizeof(float);
// //tab
// CTTextAlignment tabalignment = kCTJustifiedTextAlignment;
// CTTextTabRef texttab = CTTextTabCreate(tabalignment, 24, NULL);
// CTParagraphStyleSetting tab;
// tab.spec = kCTParagraphStyleSpecifierTabStops;
// tab.value = &texttab;
// tab.valueSize = sizeof(CTTextTabRef);
//tab
CTTextAlignment tabalignment = kCTJustifiedTextAlignment;
CTTextTabRef texttab = CTTextTabCreate(tabalignment, 24, NULL);
CTTextTabRef tabArray[] = {texttab};
CFArrayRef tabStops = CFArrayCreate( kCFAllocatorDefault, (const void**) tabArray, 1, &kCFTypeArrayCallBacks );
CFRelease(tabArray[0]);
CTParagraphStyleSetting tab;
tab.spec = kCTParagraphStyleSpecifierTabStops;
tab.value = &tabStops;
tab.valueSize = sizeof(CFArrayRef);
/*
换行模式:
kCTLineBreakByWordWrapping = 0, //出现在单词边界时起作用,如果该单词不在能在一行里显示时,整体换行。此为段的默认值。
kCTLineBreakByCharWrapping = 1, //当一行中最后一个位置的大小不能容纳一个字符时,才进行换行。
kCTLineBreakByClipping = 2, //超出画布边缘部份将被截除。
kCTLineBreakByTruncatingHead = 3, //截除前面部份,只保留后面一行的数据。前部份以...代替。
kCTLineBreakByTruncatingTail = 4, //截除后面部份,只保留前面一行的数据,后部份以...代替。
kCTLineBreakByTruncatingMiddle = 5 //在一行中显示段文字的前面和后面文字,中间文字使用...代替。
*/
//换行模式
CTParagraphStyleSetting lineBreakMode;
CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping;//kCTLineBreakByWordWrapping;//换行模式
lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
lineBreakMode.value = &lineBreak;
lineBreakMode.valueSize = sizeof(CTLineBreakMode);
//多行高
CGFloat MutiHeight = 2.0f;
CTParagraphStyleSetting Muti;
Muti.spec = kCTParagraphStyleSpecifierLineHeightMultiple;
Muti.value = &MutiHeight;
Muti.valueSize = sizeof(float);
//最大行高
CGFloat MaxHeight = 5.0f;
CTParagraphStyleSetting Max;
Max.spec = kCTParagraphStyleSpecifierLineHeightMultiple;
Max.value = &MaxHeight;
Max.valueSize = sizeof(float);
//行距
CGFloat _linespace = 5.0f;
CTParagraphStyleSetting lineSpaceSetting;
lineSpaceSetting.spec = kCTParagraphStyleSpecifierLineSpacing;
lineSpaceSetting.value = &_linespace;
lineSpaceSetting.valueSize = sizeof(float);
//段前间隔
CGFloat paragraphspace = 5.0f;
CTParagraphStyleSetting paragraph;
paragraph.spec = kCTParagraphStyleSpecifierLineSpacing;
paragraph.value = ¶graphspace;
paragraph.valueSize = sizeof(float);
/*
kCTWritingDirectionNatural = -1, //普通书写方向,一般习惯是从左到右写
kCTWritingDirectionLeftToRight = 0, //从左到右写
kCTWritingDirectionRightToLeft = 1 //从右到左写
*/
//书写方向
CTWritingDirection wd = kCTWritingDirectionRightToLeft;
CTParagraphStyleSetting writedic;
writedic.spec = kCTParagraphStyleSpecifierBaseWritingDirection;
writedic.value = &wd;
writedic.valueSize = sizeof(CTWritingDirection);
//组合设置
CTParagraphStyleSetting settings[] = {
// alignmentStyle,
// fristline,
// head,
// tail,
// tab,
// lineBreakMode,
// Muti,
// Max,
// lineSpaceSetting,
writedic
// indentSetting,
};
//通过设置项产生段落样式对象
CTParagraphStyleRef style = CTParagraphStyleCreate(settings, 11);
// build attributes
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(__bridge id)style forKey:(id)kCTParagraphStyleAttributeName ];
// set attributes to attributed string
[mabstring addAttributes:attributes range:NSMakeRange(0, slen)];
参考文章: IOS CoreText.framework --- 基本用法 study-coretext IOS CoreText.framework --- 段落样子CTParagraphStyle