ios TextKit中font相关

之前做模拟锁屏界面展示时间的时候,会发现其中的冒号会在ios7系统下变成方冒号,后来同事说可以借用UIFont的fontDescriptor来解决这个问题,而这个fontDescriptor是在苹果大大在介绍TextKit中提出,下面介绍下TextKit相关知识。

介绍

在ios7中引入了TextKit

Text Kit指的是UIKit框架中用于提供高质量排版服务的一些类和协议,它让程序能够存储,排版和显示文本信息,并支持排版所需要的所有特性,包括字距调整、连写、换行和对齐等。

如下图可以看到其所处位置(图片来自官方文档)


TextKit位置

Text Kit主要的对象如下图(图片来自官方文档),
Text views对应UITextView类,用于展示文本内容;

在 TextKit 中,文本视图有两个目的:第一,它是文本系统用来绘制的视图。文本视图它自己并不会做任何绘制;它仅仅提供一个供其它类绘制的区域。作为视图层级机构中唯一的组件,第二个目的是处理所有的用户交互。具体来说,文本视图实现 UITextInput 的协议来处理键盘事件,它为用户提供了一种途径来设置一个插入点或选择文本。它并不对文本做任何实际上的改变,仅仅将这些改变请求转发给刚刚讨论的文本存储。

Text containers对应NSTextContainer类,用于定义文本置于哪一块,通常其是一个矩形区域,你也可以自定义成其他形状;
Layout manager对应NSLayoutManager类,用于对文本版面布局;
Text storage对应NSTextStorage类,其是NSMutableAttributedString的子类,用于存储文本内容,同时它也管理一系列NSLayoutManager对象,当文本的属性或字符发生变化的时候,通知NSLayoutManager对象重新布局和展示。


TextKit主要对象

Text kit 常用的功能列举

1.对文字进行分页或多列排版
2.支持文字的换行、折叠和着色等处理
3.可以调整字与字之间的距离、行间距、文字大小、指定特定的字体
4.支持富文本编辑,可以自定义文字截断
5.支持凸版印刷效果(letterpress)
6.支持数据类型的检测(例如链接、附件等)

字体相关

  1. 系统原生字体
    一般没有特殊字体的要求,我们会用如下设定特定大小的文本
[UIFont systemFontOfSize:xx];

但是除此之外,可能也会需要加上格外的字体格式,可以用如下代码查看系统提供的字体格式有哪些,也可以访问ios字体预览

//系统提供所有字体家族名
[UIFont familyNames];
//每个字体家族名下各个字体名称
[[UIFont fontNamesForFamilyName:[[UIFont familyNames] objectAtIndex:section]]
//应用某个字体
UIFont *font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:20];
  1. 动态字体
    在设置->通用->辅助功能->更大字体,打开开关,点击进入可以调整字体大小,系统中字体会随之更改


    调整字体大小

    如果想要让你的应用中字体大小也能随着系统设置而改变,可以通过如下代码,建议动态字体和自动布局结合起来使用

UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];

但是如果程序在运行时,用户切换到设置里修改了字体,这是在切回程序,字体并不会自动跟着变。这时就需要我们自己来更新一下控件的字体了。
在系统字体修改时,系统会给运行中的程序发送UIContentSizeCategoryDidChangeNotification通知,我们只需要监听这个通知,并重新设置一下字体即可。

 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(preferredContentSizeChanged:)
                                                 name:UIContentSizeCategoryDidChangeNotification
                                               object:nil];
-(void)preferredContentSizeChanged:(NSNotification *)notification{
  self.textView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
}
文本常量 用处
UIFontTextStyleHeadline headings
UIFontTextStyleBody body text
UIFontTextStyleSubheadline subheads
UIFontTextStyleFootnote footnotes
UIFontTextStyleCaption1 standard captions
UIFontTextStyleCaption2 alternate captions

3.字体描述符
即UIFontDescriptor,通过定义字体的一系列属性来创建UIFont对象,你可以从font descriptor获取到一个font对象,也可以从font对象中得到一个font descriptor,因此你可以通过更改font descriptor得到一个新的font对象。
你可以通过font descriptor获取到font family name下的所有font

UIFontDescriptor *helveticaNeueFamily = [UIFontDescriptor fontDescriptorWithFontAttributes:@{ UIFontDescriptorFamilyAttribute: @"Helvetica Neue" }];
NSArray *matches = [helveticaNeueFamily matchingFontDescriptorsWithMandatoryKeys: nil];

matches返回系统下所有与Helvetica Neue有关的字体
HelveticaNeue,
HelveticaNeue-Medium,
HelveticaNeue-Light,
HelveticaNeue-Thin
动态字体也可以用font descriptor来定义,还可以定义symbolic traits(bold,italic,expanded,condensed),具体如下

UIFontDescriptor *fontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle: UIFontTextStyleBody];
UIFontDescriptor *boldFontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits: UIFontDescriptorTraitBold];
UIFont *boldFont = [UIFont fontWithDescriptor: boldFontDescriptor size: 0.0];
//size为0,因为这边是动态字体,是随着系统设置变化

再介绍一个官方讲解应用font descriptor设置时间展示


时间展示

我们需要的是下面的那种格式,代码如下

NSArray *timeFeatureSettings = @[
                                     @{
                                         UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
                                         UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector)
                                         },
                                     @{
                                         UIFontFeatureTypeIdentifierKey: @(kCharacterAlternativesType),
                                         UIFontFeatureSelectorIdentifierKey: @(1)
                                         }];
UIFont *font = [UIFont systemFontOfSize:20];
UIFontDescriptor *originalDescriptor = [font fontDescriptor];
UIFontDescriptor *timeDescriptor = [originalDescriptor fontDescriptorByAddingAttributes: @{UIFontDescriptorFeatureSettingsAttribute:timeFeatureSettings }];
UIFont *timeFont = [UIFont fontWithDescriptor: timeDescriptor
                                         size: 0.0];

引入外部字体

  1. 字体文件后缀是ttf,ttc,otf,otc
  2. 在app bundle中添加
    a.将字体文件放入项目中;
    b.修改plist文件,添加Fonts provided by application 配置,在其中添加item体文件名带后缀;
    c.可以在图形化界面看到新的字体选择,或者像前面那样获取所有字体名称,查看是不是有新添加的
  3. 手动添加
    CTFontManagerRegisterFontsForURL()
    CTFontManagerRegisterFontsForURLs()
    CTFontManagerRegisterGraphicsFont()
    CTFontManagerCreateFontDescriptorsFromURL()
    CTFontManagerCreateFontDescriptorFromData()

图文混排

利用textContainer的exclusion paths可以做到像word中文字环绕在图片周围;

-(UIBezierPath *)translatedBezierPath
{
    CGRect butterflyImageRect = [textView convertRect:imageView.frame fromView:self.view];
    UIBezierPath *newButterflyPath = [UIBezierPath bezierPathWithRect:butterflyImageRect];
    return newButterflyPath;
}
textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 40, [UIScreen mainScreen].bounds.size.width - 40, [UIScreen mainScreen].bounds.size.height - 40)];
textView.font = [UIFont systemFontOfSize:18];
textView.text = @"在排版中,图文混排是非常常见的需求,但有时候我们的图片并一定都是正常的矩形,这个时候我们如果需要将文本环绕在图片周围,就可以用路径排除了。Explosion pats基本原理是将需要被文本留出来的形状的路径告诉文本控件的NSTextContainer对象,NSTextContainer在文字排版时就会避开该路径。";//设置它显示的内容
    
  imageView = [[UIImageView alloc ] init];
  imageView.frame = CGRectMake(80, 80, 100, 100);
  imageView.backgroundColor = [UIColor redColor];
  UIImage *image = [UIImage imageNamed:@"0.jpeg"];
  imageView.image = image;
    
  [self.view addSubview:textView];
  [self.view addSubview:imageView];
    
  textView.textContainer.exclusionPaths = @[[self translatedBezierPath]];

运行之后,就会得到如下效果


文字环绕图片

参考资料

Using Text Kit to Draw and Manage Text
Using Fonts with Text Kit
Using Fonts with Text Kit PPT讲解
Text Kit入门
浅析Text Kit
了解ios字体相关知识
ios字体预览
Core Text Font Manager Reference

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

推荐阅读更多精彩内容