iOS中关于AttributedString的那些事儿

一、关于AttributedString

在iOS开发过程中系统简单的封装工具已经不够我们使用,为了更好的开发,苹果公司为开发者提供了一套丰富的API供开发者们使用。其中开发过程中使用最多的就是AttributedString了吧,AttributedString与NSString类似,在iOS中AttributedString也分为NSAttributedString和NSMutableAttributedString,不同的是,AttributedString对象多了一个Attribute的概念,一个AttributedString的对象包含很多的属性,每一个属性都有其对应的字符区域,使用NSRange来进行描述。下面简单讲解一下AttributedString的属性及用法。
官方学习链接Attributed String Programming Guide

  • 1.方式一:

    首先初始化一个NSMutableAttributedString,然后向里面添加文字样式,最后将它赋给控件的AttributedText,该方法适合于文本较少而又需要分段精细控制的情况。

NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是第一种方式,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈"];
 [attrStr addAttribute: NSFontAttributeName value: [UIFont fontWithName: @"Papyrus" size: 15] range: NSMakeRange(0, attrStr.length)];
  NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
  style.lineSpacing = 5.0;
  [attrStr addAttribute: NSParagraphStyleAttributeName value: style range: NSMakeRange(0, attrStr.length)];
  self.firstLabel.attributedText = attrStr;
  • 2.方式二:

首先创建属性字典,初始化各种属性,然后和需要控制的文本一起创建并赋值给控件的AttributedText,该方法适合于需要控制的文本较多整体控制的情况,通常是从文件中读取的大段文本控制。

   //第二种方式
   NSDictionary * dict = @{NSFontAttributeName:[UIFont fontWithName: @"Papyrus" size: 15], [UIFont fontWithName: @"Papyrus" size: 15]:style  };
   NSMutableAttributedString * attrStr2 = [[NSMutableAttributedString alloc] initWithString:@"我是第二种方式,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈" attributes:dict];
   self.secondLabel.attributedText = attrStr2;
1.png

二 、 AttributedString究竟可以设置哪些属性

    1. NSFontAttributeName

设置字体属性,默认值:字体:Helvetica(Neue) 字号:12
获取系统的字体:[UIFont familyNames]

   NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSFontAttributeName 字体:Papyrus 字号:15"];
   [attrStr addAttribute: NSFontAttributeName value: [UIFont fontWithName: @"Papyrus" size: 15] range: NSMakeRange(0, attrStr.length)];
2.1.png
  • NSParagraphStyleAttributeName(后面具体讲解)

该属性所对应的值是一个 NSParagraphStyle/NSMutableParagraphStyle 对象。该属性在一段文本上应用多个属性。

  NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
   style.lineSpacing = 10.0;
   NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSParagraphStyleAttributeName \\\\\\\\\\\\\\\\n行间距 10"];
     [attrStr addAttribute: NSParagraphStyleAttributeName value: style range: NSMakeRange(0, attrStr.length)];
2.2.png
  • NSForegroundColorAttributeName

设置字体颜色,取值为 UIColor对象,默认值为黑色

NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSForegroundColorAttributeName 颜色orangeColor"];
 [attrStr addAttribute: NSForegroundColorAttributeName value: [UIColor orangeColor] range: NSMakeRange(0, attrStr.length)];
2.3.png
  • NSBackgroundColorAttributeName

设置字体所在区域背景颜色,取值为 UIColor对象,默认值为nil, 透明色

    NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSBackgroundColorAttributeName 背景颜色red"];
    [attrStr addAttribute: NSBackgroundColorAttributeName value: [UIColor redColor] range: NSMakeRange(0, attrStr.length)];
2.4.png
  • NSLigatureAttributeName

设置连体属性,取值为NSNumber 对象(整数),0 表示没有连体字符,1 表示使用默认的连体字符。2 表示使用所有连体符号。默认值为 1(注意,iOS 不支持值为 2)如下图'f' 'l'的连接

 NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSLigatureAttributeName 'fl' 连体属性 0"];
  [attrStr addAttribute: NSFontAttributeName value: [UIFont fontWithName: @"PingFang SC" size: 15] range: NSMakeRange(0, attrStr.length)];
   [attrStr addAttribute: NSLigatureAttributeName value: @(0) range: NSMakeRange(0, attrStr.length)];
![2.5.2.png](http://upload-images.jianshu.io/upload_images/1429107-c9ad3521232a48d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • NSKernAttributeName

设定字符间距,取值为 NSNumber 对象(整数),正值间距加宽,负值间距变窄。

 NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSKernAttributeName  字符间距 2"];
 [attrStr addAttribute: NSKernAttributeName value: @(2) range: NSMakeRange(0, attrStr.length)];
2.6.png
  • NSStrikethroughStyleAttributeName

设置删除线,取值为 NSNumber 对象(整数)

NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSStrikethroughStyleAttributeName  删除线 1"];
 [attrStr addAttribute: NSStrikethroughStyleAttributeName value: @(1) range: NSMakeRange(0, attrStr.length)];
2.7.png
  • NSUnderlineStyleAttributeName

设置下划线,取值为 NSNumber 对象(整数),枚举常量 NSUnderlineStyle中的值。默认值是NSUnderlineStyleNone。


2.8.png
  • NSStrokeColorAttributeName

设置填充颜色。取值为 UIColor 对象,需要和NSStrokeWidthAttributeName设置描边宽度,这样就能使文字产生镂空效果。

 NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSStrokeColorAttributeName 配合NSStrokeWidthAttributeName使用"];
 [attrStr addAttribute: NSStrokeColorAttributeName value: [UIColor redColor] range: NSMakeRange(0, attrStr.length)];
 [attrStr addAttribute: NSStrokeWidthAttributeName value: @(2) range: NSMakeRange(0, attrStr.length)];
2.9.png
  • NSStrokeWidthAttributeName

设置笔画宽度,取值为 NSNumber 对象(整数),负值填充效果,正值中空效果。与NSStrokeColorAttributeName配合使用

 NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSStrokeWidthAttributeName 配合NSStrokeColorAttributeName使用"];
 [attrStr addAttribute: NSStrokeWidthAttributeName value: @(-2) range: NSMakeRange(0, attrStr.length)];
  [attrStr addAttribute: NSStrokeColorAttributeName value: [UIColor blueColor] range: NSMakeRange(0, attrStr.length)];
2.10.png
  • NSShadowAttributeName

设置阴影属性,取值为 NSShadow 对象。默认为 nil。

NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSShadowAttributeName 竖直方向偏移 15"];
 NSShadow * shadow = [[NSShadow alloc] init];
 shadow.shadowColor = [UIColor grayColor];
shadow.shadowOffset = CGSizeMake(0, 15);
 [attrStr addAttribute: NSShadowAttributeName value:shadow range: NSMakeRange(0, attrStr.length)];
2.11.png
  • NSTextEffectAttributeName

设置文本特殊效果,取值为 NSString 对象,目前只有图版印刷效果可用NSTextEffectLetterpressStyle。

  NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSTextEffectAttributeName 模式NSTextEffectLetterpressStyle"];
 [attrStr addAttribute: NSTextEffectAttributeName value:NSTextEffectLetterpressStyle range: NSMakeRange(0, attrStr.length)];
2.12.png
  • NSAttachmentAttributeName

设置文本附件,取值为NSTextAttachment对象,常用于文字图片混排

  NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSAttachmentAttributeName "];
   NSTextAttachment * textAtt = [[NSTextAttachment alloc] init];
   textAtt.image = [UIImage imageNamed:@"tag_d"];
    textAtt.bounds = CGRectMake(0, 0, 44, 44);
    NSAttributedString *attrStr2 = [NSAttributedString attributedStringWithAttachment: textAtt];
    [attrStr insertAttributedString: attrStr2 atIndex: 6];
2.13.png
  • NSLinkAttributeName

设置链接属性,对象是NSURL点击后调用浏览器打开指定URL地址
推荐一款非常好用的轮子 TTTAttributedLabel
UITextView *textView = [[UITextView alloc] init];
textView.scrollEnabled = NO;
textView.editable = NO;
textView.frame =cell.bounds;
textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
textView.delegate = self;
attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSLinkAttributeName 测试 百度"];
[attrStr addAttribute: NSLinkAttributeName value:[NSURL URLWithString: @"http://www.baidu.com"] range: NSMakeRange(0, attrStr.length)];
textView.attributedText = attrStr;

  • NSBaselineOffsetAttributeName

设置基线偏移值,取值为 NSNumber (float),正值上偏,负值下偏

NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSBaselineOffsetAttributeName 偏移5"];
 [attrStr addAttribute: NSBaselineOffsetAttributeName value: @(5) range: NSMakeRange(0, attrStr.length)];
2.15.png
  • NSUnderlineColorAttributeName

设置下划线颜色,取值为 UIColor 对象,默认值为黑色

NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSUnderlineColorAttributeName "];
[attrStr addAttribute: NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range: NSMakeRange(0, attrStr.length)];
 [attrStr addAttribute: NSUnderlineColorAttributeName value:[UIColor yellowColor] range: NSMakeRange(0, attrStr.length)];
2.16.png
  • NSStrikethroughColorAttributeName

设置删除线颜色,取值为 UIColor 对象,默认值为黑色

NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSStrikethroughColorAttributeName "];
  [attrStr addAttribute: NSStrikethroughStyleAttributeName value:@(1) range: NSMakeRange(0, attrStr.length)];
 [attrStr addAttribute: NSStrikethroughColorAttributeName value:[UIColor brownColor] range: NSMakeRange(0, attrStr.length)];
2.17.png
  • NSObliquenessAttributeName

设置字形倾斜度,取值为 NSNumber (float),正值右倾,负值左倾

 NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSStrikethroughColorAttributeName 右倾斜"];
  [attrStr addAttribute: NSObliquenessAttributeName value:@(1) range: NSMakeRange(0, attrStr.length)];
2.18.png
  • NSExpansionAttributeName

设置文本横向拉伸属性,取值为 NSNumber (float),正值横向拉伸文本,负值横向压缩

   NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSExpansionAttributeName 横向压"];
   [attrStr addAttribute: NSFontAttributeName value: [UIFont fontWithName: @"Papyrus" size: 12] range: NSMakeRange(0, attrStr.length)];
  [attrStr addAttribute: NSExpansionAttributeName value:@(1) range: NSMakeRange(0, attrStr.length)];
2.19.png
  • NSWritingDirectionAttributeName

设置文字书写方向,取值为以下组合

@[@(NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding)];  
    @[@(NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding)];   
    @[@(NSWritingDirectionLeftToRight|NSWritingDirectionOverride)];
     @[@(NSWritingDirectionRightToLeft|NSWritingDirectionOverride)];
NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSWritingDirectionAttributeName 方式NSWritingDirectionLeftToRight&Embedding"];
 [attrStr addAttribute: NSWritingDirectionAttributeName value:@[@(NSWritingDirectionLeftToRight | NSWritingDirectionEmbedding)] range: NSMakeRange(0, attrStr.length)];
2.20.png
  • NSVerticalGlyphFormAttributeName

文本方向,取值为 NSNumber 对象(整数)。0 表示横排文本。1 表示竖排文本。在 iOS 中,总是使用横排文本,0 以外的值都未定义。

 NSAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"我是NSVerticalGlyphFormAttributeName "];
 [attrStr addAttribute: NSVerticalGlyphFormAttributeName value:@(0) range: NSMakeRange(0, attrStr.length)];
2.21.png
  • NSDocumentTypeDocumentAttribute

直接进行 html 的展示

NSString * htmlString = @"<html><body> Some html string \n <font size=\"13\" color=\"red\">This is some text!This is some text!This is some text!This is some text!This is some text!</font> </body></html>";
 attrStr = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
22.png

三、关于计算

1 .在7.0以后官方计算的API

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSString *, id> *)attributes context:(nullable NSStringDrawingContext *)context NS_AVAILABLE(10_11, 7_0);

参数
size:
宽高限制,用于计算文本绘制时占据的矩形块。
options:
文本绘制时的附加选项。可能取值请参考“NSStringDrawingOptions”。
attributes:
文本绘制时用到的AttributedString的属性,就是文中提到的20几种。
context:
context上下文。包括一些信息,例如如何调整字间距以及缩放。最终,该对象包含的信息将用于文本绘制。该参数一般为 nil 。
返回值:
一个矩形,大小等于文本绘制完将占据的宽和高。
具体计算方式,example

-(CGFloat)getSpaceLabelHeight:(NSString*)str withFont:(UIFont*)font withWidth:(CGFloat)width
{
    NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
    paraStyle.alignment = NSTextAlignmentLeft;
    paraStyle.lineSpacing = 4;
    NSDictionary *dic = @{NSFontAttributeName:font, NSParagraphStyleAttributeName:paraStyle
                          };
    
    CGSize size = [str boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;
    return size.height;
}

2 .计算真实的大小,sizeThatFits

- (CGSize)sizeThatFits:(CGSize)size;     // return 'best' size to fit given size. does not actually resize view. Default is return existing view size

3 . 自适应,sizeToFit

- (void)sizeToFit;                       // calls sizeThatFits: with current view bounds and changes bounds size.

视具体情况而定,灵活应用上面三种方式计算即可,满足绝大多数需求。

:NSParagraphStyle的属性参考

属性 解读
lineSpacing CGFloat类型,行距
paragraphSpacing CGFloat类型,段距
alignment NSTextAlignment,对齐方式
firstLineHeadIndent CGFloat类型,首行缩进
headIndent CGFloat类型,缩进
tailIndent CGFloat类型,尾部缩进
lineBreakMode CGFloat类型,断行方式
minimumLineHeight CGFloat类型,最小行高
maximumLineHeight CGFloat类型,最大行高
baseWritingDirection NSWritingDirection,句子方向
lineHeightMultiple CGFloat类型,可变行高,乘因数
paragraphSpacingBefore CGFloat类型,段首空间
hyphenationFactor CGFloat类型,连字符属性

照例放Demo,仅供参考
Demo地址:
https://github.com/yongliangP/AttributedStringDemo
如果你觉得对你有帮助请点喜欢哦,也可以关注我,每周至少一篇技术。
或者关注 我的专题 每周至少5篇更新,多谢支持哈。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容