cocoa touch layer下面的几个点连载之--CoreText

cocoa touch layer下面的几个点连载之--CoreText,第1张

概述coreText自定义富文本LabelUILabel是经常使用的一种控件,iOS上的UILabel已经能很好满足一些需求。比如设置对齐方式,换行模式等等。但如果需求是需要一串字符中不同的字符颜色,字体都单独设置,UILabel就无法满足了。那就自己来做个富文本Label好了。先创建继承UILabel的AttributedLabel.h,AttributedLabel.m文件,重载UILabe
coreText自定义富文本LabelUILabel是经常使用的一种控件,iOS上的UILabel已经能很好满足一些需求。比如设置对齐方式,换行模式等等。但如果需求是需要一串字符中不同的字符颜色,字体都单独设置,UILabel就无法满足了。那就自己来做个富文本Label好了。先创建继承UILabel的AttributedLabel.h,AttributedLabel.m文件,重载UILabeld -(voID)drawTextInRect:(CGRect)rect方法,我们的文本绘制就放在这个函数中。使用coreText进行文本绘制,需要在工程中添加CoreText.framework,然后在AttributedLabel.m里import<CoreText/CoreText.h>就可以使用了。coreText负责绘制,那绘制的内容和属性则要靠NSAttributedString来存储,如果属性具有不确定性,可以使用NSMutableAttributedString,方便后面添加属性。先来看下如何创建一个具有两个颜色,两种字体的“hello world”的NSMutableAttributedString实例。Nsstring *text = @“hello word”; NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text]; [attributedText addAttribute:(Nsstring*)(kCTForegroundcolorAttributename) value:(ID)[[UIcolor bluecolor]CGcolor] range:NSMakeRange(0,5)]; [attributedText addAttribute:(Nsstring*)(kCTForegroundcolorAttributename) value:(ID)[[UIcolor redcolor]CGcolor] range:NSMakeRange(6,5)]; CTFontRef  Font_hello = CTFontCreateWithname((CFStringRef)@“Helvetica”,16,NulL); CTFontRef  Font_world = CTFontCreateWithname((CFStringRef)@“GillSans”,20,NulL); [attributedText addAttribute: (Nsstring*)(kCTFontAttributename) value:(ID)Font_hello range:NSMakeRange(0,5)]; [attributedText addAttribute: (Nsstring*)(kCTFontAttributename) value:(ID)Font_world range:NSMakeRange(6,5)];这样,一个包含简单绘制属性的NSMutableAttributedString实例就创建出来了。接下来就要在drawTextInRect函数中开始绘制了。普通视图坐标系原点在左上方,而QuartZ绘图的坐标系原点在左下方,所以我们先要调整坐标系。CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context,CGAffinetransformIDentity);//重置 CGContextTranslateCTM(context,self.bounds.size.height); //y轴高度 CGContextScaleCTM(context,1.0,-1.0);//y轴翻转好了,可以开始绘制,因为”hello world”较短,一行就可以放下,那么可以这么绘制CTlineRef line = CTlineCreateWithAttributedString(attributedText); CGContextSetTextposition(context,0); CTlineDraw(line,context); CFRelease(line);OK,就这么多搞定。那如果文本很长,希望换行来显示怎么办?那我们先要给attributedText添加些关于行相关属性。下面都是基本的,可以根据自己绘制情况调整,扩充相应的变量。CTlineBreakMode lineBreakMode = kCTlineBreakByWorDWrapPing;//换行模式 CTTextAlignment alignment = kCTleftTextAlignment;//对齐方式 float linespacing =2.0;//行间距 CTParagraphStyleSetting paraStyles[3] = { {.spec = kCTParagraphStyleSpecifIErlineBreakMode,.valueSize = sizeof(CTlineBreakMode),.value = (const voID*)&lineBreakMode},{.spec = kCTParagraphStyleSpecifIErAlignment,.valueSize = sizeof(CTTextAlignment),.value = (const voID*)&alignment},{.spec = kCTParagraphStyleSpecifIErlinespacing,.valueSize = sizeof(CGfloat),.value = (const voID*)&linespacing},}; CTParagraphStyleRef style = CTParagraphStyleCreate(paraStyles,3); [attributedText addAttribute:(Nsstring*)(kCTParagraphStyleAttributename) value:(ID)style range:NSMakeRange(0,[text length])]; CFRelease(style);下面就可以绘制了CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedText); CGMutablePathref path = CGPathCreateMutable(); CGPathAddRect(path,NulL,self.bounds); CTFrameRef frame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0),path,NulL); CGContextSetTextposition(context,0); CTFrameDraw(frame,context); CFRelease(framesetter); CFRelease(frame);这样绘制出来的可以自适应换行了,或者可以做的复杂点,通过上面获取的CTFrameRef frame来得到CTlineRef绘制CFArrayRef lines = CTFrameGetlines(frame); int lineNumber = CFArrayGetCount(lines); CGPoint lineOrigins[lineNumber]; CTFrameGetlineOrigins(frame,lineNumber),lineOrigins); for(int lineIndex = 0;lineIndex < lineNumber;lineIndex++){ CGPoint lineOrigin = lineOrigins[lineIndex]; CTlineRef line = CFArrayGetValueAtIndex(lines,lineIndex); CGContextSetTextposition(context,lineOrigin.x,lineOrigin.y); CTlineDraw(line,context); }但这样绘制方法有个问题,就是即使行间距设为0.0(不能为负值)仍是比较分散的。如果希望更进一步控制好行间距,那自己就一行一行计算位置画float lineHeight = 20; //行高 BOol drawFlag = YES;//是否绘制 int lineCount = 0;//行数 CFIndex currentIndex = 0;//绘制计数 CTTypesetterRef typeSetter = CTTypesetterCreateWithAttributedString((CFAttributedStringRef)attributedText); float FontAscender = MAX(Font_hello.ascender,Font_world.ascender); float y = self.bounds.origin.y+self.bounds.size.height-FontAscender; while(drawFlag) { CFIndex lineLength = CTTypesetterSuggestlineBreak(typeSetter,currentIndex,self.bounds.size.wIDth); CFRange lineRange = CFRangeMake(currentIndex,lineLength); CTlineRef line = CTTypesetterCreateline(typeSetter,lineRange); float x = CTlineGetPenOffsetForFlush(line,self.bounds.size.wIDth); CGContextSetTextposition(context,x,y); CTlineDraw(line,context); if(currentIndex + lineLength >= [text length]){ drawFlag = NO; } CFRelease(line); count++; y -=lineHeight; currentIndex += lineLength; } CFRelease(typeSetter);到这里的时候,又有个问题,就是用同样的字体和字号,绘制的字总是会比UILabel显示的粗些。查看kCTstrokeWIDthAttributename属性发现默认已经为0.0,但这个值是可以为负值,那就变通的解决这个问题。在attributedText里添加两个属性值CGfloat wIDthValue = -1.0; CFNumberRef strokeWIDth = CFNumberCreate(NulL,kcfNumberfloatType,&wIDthValue); [attributedText addAttribute:(Nsstring*)(kCTstrokeWIDthAttributename) value:(ID)strokeWIDth range:NSMakeRange(0,[text length])]; [attributedText addAttribute:(Nsstring*)(kCTstrokecolorAttributename) value:(ID)[[UIcolor whitecolor]CGcolor] range:NSMakeRange(0,[text length])];这样绘制出来的字就细致些。好了,沿着这条线的内容大致说完,有兴趣的自己敲一敲吧
总结

以上是内存溢出为你收集整理的cocoa touch layer下面的几个点连载之--CoreText全部内容,希望文章能够帮你解决cocoa touch layer下面的几个点连载之--CoreText所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1059171.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存