ios NSAttributedString 具体解释

NSAttributedString能够让我们使一个字符串显示的多样化,可是眼下到iOS 5为止,好像对它支持的不是非常好,由于显示起来不太方便(至少没有在OS X上方便)。

首先导入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
  1. value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble]
  2. range:NSMakeRange(0, 4)];
  3. 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!

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

效果图:

源代码地址

-----------------------------------------猥琐的分界线-----------------------------------------
眼下发现有一个问题,好像中文全都会被加粗,设置不加粗的字体也没用,应该是CoreText的bug,已经上报给了apple了。

-----------------------------------------对于cythb兄提出的问题-----------------------------------------
首先表示感谢关注

原文中确有描写叙述不适当的地方,比方:The upper-left corner of the context is (0, 0) 。实际上Quartz2D的坐标系统确实在左下角,仅仅是有一些技术在设置它们的graphics
context时使用了不同于Quartz的默认坐标系统。相对于Quartz来说,这些坐标系统是改动的坐标系统(modified coordinate system)。

UPDATED

在iOS6之后,创建一个AttributedString变成了一件轻松的事情,<CoreText/CoreText.h>已经不须要导入了。假设我要设置字体的颜色,能够直接这样:

  1. [textAttr addAttribute:NSForegroundColorAttributeName
  2. value:[UIColor redColor]
  3. range:NSMakeRange(0, text.length)];

ios NSAttributedString 具体解释的更多相关文章

  1. iOS SDK具体解释之NSCopying协议

    原创blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=contents 欢迎关注我的iOS SDK具体解释专栏 http://blog.csdn ...

  2. iOS SDK具体解释之UIDevice(系统版本号,设备型号...)

    原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK具体解释专栏 blog.csdn.net/column/details/huangwenchen ...

  3. iOS Animation具体解释

    iOS Animation具体解释 本篇仅仅要解说iOS中动画的使用. Animtion主要分为两类:UIView动画和CoreAnimation动画. UIView动画有UIView属性动画,UIV ...

  4. iOS --NSAttributedString

    字符属性可以应用于 attributed string 的文本中. 文/iOS_成才录(简书作者) 原文链接:http://www.jianshu.com/p/03a741246737 著作权归作者所 ...

  5. iOS 严重问题解释(crash)

    问题1:Exception Type: 00000020 Exception Codes: 0x000000008badf00d Exception Note: SIMULATED (this is  ...

  6. iOS常识名词解释 2016/04/05

    Bundle : http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/2421802.html http://blog.sina.com.cn ...

  7. 【精】iOS GCD 具体解释

    一.介绍 1.什么是GCD? Grand Central Dispatch.是苹果公司开发的一套多核编程的底层API. GCD首次公布在Mac OS X 10.6,iOS4及以上也可用.GCD存在于l ...

  8. 关于IOS框架的解释

  9. iOS Core Animation具体解释(四)AutoLayout中的动画

    原创blog.转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK具体解释专栏 http://blog.csdn.net/column/details/huang ...

随机推荐

  1. 【实验吧】guess next session&&FALSE&&NSCTF web200&&程序逻辑问题

      guess next session源码: <?php session_start(); if (isset ($_GET['password'])) { if ($_GET['passwo ...

  2. Verilog学习笔记基本语法篇(八)········ 结构说明语句

    Verilog中的任何过程都可以属于以下四种结构的说明语句; 1) initial;  2) always;  3) task;   4) function; 1) initial说明语句: 一个程序 ...

  3. Java实现——字符串分割以及复制目录下的所有文件

    0.  前言 今天有个需求,把Android中data/data目录下指定(通过读预置的XML文件)的多个应用下的多个目录全部内容通过OTG模式复制到U盘中. 首先读取XML文件内的某个节点的属性值, ...

  4. Experiments done

    喷重金属 换重金属溶液 荧光光合 备注 ASD 备注 高光谱 备注 泡EDTA 备注 电镜 备注 2018.12.19(day1) 2018.12.19(day1) 2018.12.18晚(day0) ...

  5. 17,时间模块 time,random模块

    表示时间的三种方式 在python中,通常有着三种方式来表示时间:时间戳,元祖,格式化的时间字符串: 1,时间戳(timestamp):通常来说时间戳表示的是从1970年1月1日00:00:00开始按 ...

  6. 检测SQLserver数据库链接是否正常

    select * From [数据库链接名].master.dbo.sysdatabases where name='数据库名' and status<>512

  7. 【java基础 6】java的发展史简介

    结合到近期在做springboot框架开发遇到的关于jdk版本的问题,本篇博客,主要介绍一下java的发展历史,侧重纯文介绍每个版本的特性.--主要从理论上做个宏观的了解,不做具体的技术研究讨论! 一 ...

  8. 九度oj 题目1030:毕业bg

    题目描述:     每年毕业的季节都会有大量毕业生发起狂欢,好朋友们相约吃散伙饭,网络上称为“bg”.参加不同团体的bg会有不同的感觉,我们可以用一个非负整数为每个bg定义一个“快乐度”.现给定一个b ...

  9. 【Luogu】P3052摩天大楼里的奶牛(遗传算法乱搞)

    一道状压题,但今天闲来无事又用遗传乱搞了一下. 设了一个DNA数组,DNA[i]记录第i个物品放在哪个组里.适应度是n-这个生物的组数+1. 交配选用的是轮盘赌和单亲繁殖——0.3的几率单点变异.(事 ...

  10. SPOJ GSS5 Can you answer these queries V ——线段树

    [题目分析] GSS1上增加区间左右端点的限制. 直接分类讨论就好了. [代码] #include <cstdio> #include <cstring> #include & ...