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. 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 F题

    The Heaviest Non-decreasing Subsequence Problem 解题心得 这个题就是一个简单的动态规划,非递减最长子序列的改版(加一个权重),只要把权重为5的改成5个权 ...

  2. 【转】VS2017的VSIX插件开发

    最近从头开发了一遍一个VSIX的插件,用于调测的一个工具: 特此把相关的过程经验记录下来: 第一步:建立工程 1.      首先是安装上: 需要安装Visual Studio SDK,这个在安装VS ...

  3. kali-set

    Set 简介 开源的社会工程学利用套件,通常结合metasploit(部分)来使用 更改 /etc/setoolkit下的配置文件 set_config BLEEDING_EDGE="Fal ...

  4. Leetcode 331.验证二叉树的前序序列化

    验证二叉树的前序序列化 序列化二叉树的一种方法是使用前序遍历.当我们遇到一个非空节点时,我们可以记录下这个节点的值.如果它是一个空节点,我们可以使用一个标记值记录,例如#. 例如,上面的二叉树可以被序 ...

  5. Relay Race (DP)

    Furik and Rubik take part in a relay race. The race will be set up on a large square with the side o ...

  6. hdu2074

    我先求出交叉的gird,然后再一行一行求得.感觉还可以吧.思路比较清晰,开始想的是数是第几行然后从每一行的前后开始控制,好麻烦的感觉,我就先求出来了框架再做就好做多啦!后来PE,突然发现我特殊处理n= ...

  7. DefaultActionInvocation 源码

    /** * Copyright 2002-2006,2009 The Apache Software Foundation. * * Licensed under the Apache License ...

  8. .NET重构(八):周结账单中,给报表添加参数

    导读:进行完了日结报表的制作,大松一口气.不过,刚开始看着周结账单中的两个参数问题,也是愁了很久.不过,只要思想不滑坡,办法总比困难多.接下来,就写写我制作周结账单报表的过程. 一.添加参数 1,在日 ...

  9. 【bzoj2989】数列 KD-tree+旋转坐标系

    题目描述 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|. 2种操作(k都是正整数): 1.Mo ...

  10. gridview和detailsview的完美结合运用实现增删改

    原文发布时间为:2008-07-24 -- 来源于本人的百度文章 [由搬家工具导入] 1、因Gridview中没有增加记录,所以应利用datalistview或formview来弥补。 2、因为det ...