首先导入CoreText.framework,并在需要使用的文件中导入:

#import<CoreText/CoreText.h>

创建一个NSMutableAttributedString:

  1. NSMutableAttributedString *attriString = [[[NSMutableAttributedString alloc] initWithString:@"this is test!"]
  2. autorelease];

非常常规的创建方式,接下来我们给它配置属性:

  1. //把this的字体颜色变为红色
  2. [attriString addAttribute:(NSString *)kCTForegroundColorAttributeName
  3. value:(id)[UIColor redColor].CGColor
  4. range:NSMakeRange(0, 4)];
  5. //把is变为黄色
  6. [attriString addAttribute:(NSString *)kCTForegroundColorAttributeName
  7. value:(id)[UIColor yellowColor].CGColor
  8. range:NSMakeRange(5, 2)];
  9. //改变this的字体,value必须是一个CTFontRef
  10. [attriString addAttribute:(NSString *)kCTFontAttributeName
  11. value:(id)CTFontCreateWithName((CFStringRef)[UIFont boldSystemFontOfSize:14].fontName,
  12. 14,
  13. NULL)
  14. range:NSMakeRange(0, 4)];
  15. //给this加上下划线,value可以在指定的枚举中选择
  16. [attriString addAttribute:(NSString *)kCTUnderlineStyleAttributeName
  17. value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble]
  18. range:NSMakeRange(0, 4)];
  19. return attriString;

这样就算是配置好了,但是我们可以发现NSAttributedString继承于NSObject,并且不支持任何draw的方法,那我们就只能自己draw了。写一个UIView的子类(假设命名为TView),在initWithFrame中把背景色设为透明(self.backgroundColor = [UIColor clearColor]),然后在重写drawRect方法:

  1. -(void)drawRect:(CGRect)rect{
  2. [super drawRect:rect];
  3. NSAttributedString *attriString = getAttributedString();
  4. CGContextRef ctx = UIGraphicsGetCurrentContext();
  5. CGContextConcatCTM(ctx, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height), 1.f, -1.f));
  6. CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attriString);
  7. CGMutablePathRef path = CGPathCreateMutable();
  8. CGPathAddRect(path, NULL, rect);
  9. CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
  10. CFRelease(path);
  11. CFRelease(framesetter);
  12. CTFrameDraw(frame, ctx);
  13. CFRelease(frame);
  14. }

在代码中我们调整了CTM(current transformation matrix),这是因为Quartz 2D的坐标系统不同,比如(10, 10)到(20, 20)的直线坐标:

坐标类似于数学中的坐标,可以先不调整CTM,看它是什么样子的,下面两种调整方法是完全一样的:

  1. CGContextConcatCTM(ctx, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height), 1.f, -1.f));

==

  1. CGContextTranslateCTM(ctx, 0, rect.size.height);
  2. CGContextScaleCTM(ctx, 1, -1);

CTFramesetter是CTFrame的创建工厂,NSAttributedString需要通过CTFrame绘制到界面上,得到CTFramesetter后,创建path(绘制路径),然后得到CTFrame,最后通过CTFrameDraw方法绘制到界面上。

如果想要计算NSAttributedString所要的size,就需要用到这个API:

CTFramesetterSuggestFrameSizeWithConstraints,用NSString的sizeWithFont算多行时会算不准的,因为在CoreText里,行间距也是你来控制的。

设置行间距和换行模式都是设置一个属性:kCTParagraphStyleAttributeName,这个属性里面又分为很多子

属性,其中就包括

  • kCTLineBreakByCharWrapping
  • kCTParagraphStyleSpecifierLineSpacingAdjustment
设置如下:
  1. //段落
  2. //line break
  3. CTParagraphStyleSetting lineBreakMode;
  4. CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping; //换行模式
  5. lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
  6. lineBreakMode.value = &lineBreak;
  7. lineBreakMode.valueSize = sizeof(CTLineBreakMode);
  8. //行间距
  9. CTParagraphStyleSetting LineSpacing;
  10. CGFloat spacing = 4.0;  //指定间距
  11. LineSpacing.spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;
  12. LineSpacing.value = &spacing;
  13. LineSpacing.valueSize = sizeof(CGFloat);
  14. CTParagraphStyleSetting settings[] = {lineBreakMode,LineSpacing};
  15. CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, 2);   //第二个参数为settings的长度
  16. [attributedString addAttribute:(NSString *)kCTParagraphStyleAttributeName
  17. value:(id)paragraphStyle
  18. range:NSMakeRange(0, attributedString.length)];

-----------------------------------------猥琐的分界线-----------------------------------------

这并不是唯一的方法,还有另一种替代方案:

  1. CATextLayer *textLayer = [CATextLayer layer];
  2. textLayer.string = getAttributedString();
  3. textLayer.frame = CGRectMake(0, CGRectGetMaxY(view.frame), 200, 200);
  4. [self.view.layer addSublayer:textLayer];

CATextLayer可以直接支持NSAttributedString!

-----------------------------------------猥琐的分界线-----------------------------------------

效果图:

源码地址

http://blog.sina.com.cn/s/blog_6cffce7701016k7p.html

NSAttributedString 详解相关推荐

  1. POPSpring动画参数详解

    POPSpring动画参数详解 效果 源码 https://github.com/YouXianMing/Animations // // POPSpringParameterController.m ...

  2. ios开发text kit_IOS开发入门之TextKit详解

    本文将带你了解IOS开发入门iOS 开发 富文本详解之TextKit详解,希望本文对大家学IOS有所帮助. textkit结构 textkit使用步骤 #Mark - 1. 自定义label  --c ...

  3. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  4. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  5. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

  6. 通俗易懂word2vec详解词嵌入-深度学习

    https://blog.csdn.net/just_so_so_fnc/article/details/103304995 skip-gram 原理没看完 https://blog.csdn.net ...

  7. 深度学习优化函数详解(5)-- Nesterov accelerated gradient (NAG) 优化算法

    深度学习优化函数详解系列目录 深度学习优化函数详解(0)– 线性回归问题 深度学习优化函数详解(1)– Gradient Descent 梯度下降法 深度学习优化函数详解(2)– SGD 随机梯度下降 ...

  8. CUDA之nvidia-smi命令详解---gpu

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  9. Bert代码详解(一)重点详细

    这是bert的pytorch版本(与tensorflow一样的,这个更简单些,这个看懂了,tf也能看懂),地址:https://github.com/huggingface/pytorch-pretr ...

最新文章

  1. 明星企业内推+BAT面经,长三角的开发者联合起来!
  2. 使用cocoapods时,import 找不到头文件。
  3. Python 技术篇-index()字符串倒叙匹配获取索引,字符串切片反向输出,逆向输出字符串
  4. 前端Javascript与Nodejs的异同
  5. Java并发– CyclicBarrier示例
  6. 9月11号华为发布鸿蒙2.0和EMUI 11,来看看鸿蒙最牛逼的地方
  7. Atitit.eclipse git使用
  8. 使用GDAL的MEM内存文件保存临时文件
  9. Builder 设计模式 +lomok @Data @Builder @Builder.default
  10. JUC 常用 4 大并发工具类:CountDownLatch、CyclicBarrier、Semaphore、Exchanger
  11. 基于Chrome内核(WebKit.net)定制开发DoNet浏览器
  12. 【手写dubbo-2】超详细!netty实现群聊、私聊
  13. Beautiful Soup4.2文档
  14. “我一年赚100万,这个项目告诉你也无妨!”
  15. Python量化交易平台开发教程系列7-顶层GUI界面开发(1)
  16. java网络编程(网络通信)
  17. Xilinx FIFO使用小结
  18. 艺术对于计算机专业的应用,浅谈《计算机应用基础》课程的教学艺术
  19. 用C++写好一个基本的文本编辑软件
  20. MIPS指令集和汇编

热门文章

  1. 基础004:R语言数据处理和变换——dplyr
  2. Microbiome:重新定义“卫生”的概念
  3. Python使用matplotlib可视化小提琴图、seaborn中的violinplot函数可视化多分类变量的小提琴图(Violin Plot)
  4. R语言可视化包ggplot2改变图例(legend)的标题(title)实战
  5. python代码实现插入排序
  6. sql服务器登录名为电脑名如何修改,如何恢复数据库的账号 登录名/用户名等
  7. R语言包_manipulate
  8. 新一代测序技术Sparc
  9. STM32-USART发送程序
  10. 如何转载别人的csdn博客