CoreText
在iOS中怎樣才能將一個(gè)字符串繪制到屏幕上呢?
簡(jiǎn)單來(lái)說(shuō),是通過(guò)控件來(lái)完成的,而這些控件都封裝在UIKit框架中(對(duì)于Mac OS X是AppKit框架),在UIKit中常用來(lái)在屏幕上顯示字符串的控件有3個(gè):
UILabel
UITextField
UITextView
然而這些控件本身對(duì)文本的展現(xiàn)方式很單一,通常僅僅能夠控制字體樣式、大小、顏色、加粗、斜體等等,而對(duì)于行距控制,字距控制,段落控制等高級(jí)功能卻無(wú)能為力。
此時(shí)不免要提起一個(gè)非常強(qiáng)大的文本排版框架CoreText.framework。
CoreText框架是基于 iOS 3.2+ 和 OSX 10.5+ 的一種能夠?qū)ξ谋靖袷胶臀谋静季诌M(jìn)行精細(xì)控制的文本引擎。它良好的結(jié)合了 UIKit 和 Core Graphics/Quartz.
UIKit 的 UILabel 允許你通過(guò)在 IB 中簡(jiǎn)單的拖曳添加文本,但你不能改變文本的顏色和其中的單詞。
Core Graphics/Quartz幾乎允許你做任何系統(tǒng)允許的事情,但你需要為每個(gè)字形計(jì)算位置,并畫在屏幕上。
CoreText正結(jié)合了這兩者!你自己可以完全控制位置、布局、類似文本大小和顏色這樣的屬性,CoreText將幫你完善其它的東西——類似文本換行、字體呈現(xiàn)等等。
然而,CoreText.framework本身非常龐大,學(xué)習(xí)成本較高,使用起來(lái)也不是很方便,所以一般不是特殊需要,很少會(huì)有人去使用它。
隨著iOS6 API的發(fā)布,文字顯示的API越來(lái)越完善,其中一個(gè)重要的更新是在UITextField,UITextView和UILabel中加入了對(duì)AttributedString的支持,實(shí)現(xiàn)行距控制,字距控制,段落控制等高級(jí)功能也不必再去使用深?yuàn)W的CoreText框架。
而iOS7的發(fā)布,蘋果又引入了TextKit,TextKit是一個(gè)快速而又現(xiàn)代化的文字排版和渲染引擎。
而我們的需求通過(guò)一個(gè)簡(jiǎn)單小巧的AttributedString就可以輕松搞定,所以本文的關(guān)注點(diǎn)只有一個(gè),那就是AttributedString,至于CoreText和TextKit,在真正需要的時(shí)候再進(jìn)行深入研究和總結(jié)。
與NSString類似,在iOS中AttributedString也分為NSAttributedString和NSMutableAttributedString,不同的是,AttributedString對(duì)象多了一個(gè)Attribute的概念,一個(gè)AttributedString的對(duì)象包含很多的屬性,每一個(gè)屬性都有其對(duì)應(yīng)的字符區(qū)域,在這里是使用NSRange來(lái)進(jìn)行描述的。
富文本
NSMutableAttributedString 的使用
使用AttributedString的方式通常有兩種:
方式一:
首先初始化一個(gè)NSMutableAttributedString,然后向里面添加文字樣式,最后將它賦給控件的AttributedText,該方法適合于文本較少而又需要分段精細(xì)控制的情況。
方式二:
首先創(chuàng)建屬性字典,初始化各種屬性,然后和需要控制的文本一起創(chuàng)建并賦值給控件的AttributedText,該方法適合于需要控制的文本較多整體控制的情況,通常是從文件中讀取的大段文本控制。
詳見代碼。。。
//其實(shí)流程是這樣的: 1、生成要繪制的NSAttributedString對(duì)象。 2、生成一個(gè)CTFramesetterRef對(duì)象,然后創(chuàng)建一個(gè)CGPath對(duì)象,這個(gè)Path對(duì)象用于表示可繪制區(qū)域坐標(biāo)值、長(zhǎng)寬。 3、使用上面生成的setter和path生成一個(gè)CTFrameRef對(duì)象,這個(gè)對(duì)象包含了這兩個(gè)對(duì)象的信息(字體信息、坐標(biāo)信息),它就可以使用CTFrameDraw方法繪制了。
//壓棧,壓入圖形狀態(tài)棧中.每個(gè)圖形上下文維護(hù)一個(gè)圖形狀態(tài)棧,并不是所有的當(dāng)前繪畫環(huán)境的圖形狀態(tài)的元素都被保存。圖形狀態(tài)中不考慮當(dāng)前路徑,所以不保存
//保存現(xiàn)在得上下文圖形狀態(tài)。不管后續(xù)對(duì)context上繪制什么都不會(huì)影響真正得屏幕。
/*
本例子是實(shí)現(xiàn)類似于微博的富文本效果,可以實(shí)現(xiàn)圖文混排和處理點(diǎn)擊事件觸發(fā)。使用CoreText進(jìn)行圖文混排的核心思想是把需要擺放圖片的位置用空字符替換原來(lái)的字符,并且實(shí)現(xiàn)CTRunDelegate,用于動(dòng)態(tài)設(shè)置空字符的高度和寬度(代表圖片的大?。?,并且對(duì)這些空字符設(shè)置一個(gè)屬性名來(lái)區(qū)別于其他CTRun,之后進(jìn)行圖片渲染的時(shí)候就能通過(guò)該屬性來(lái)區(qū)分哪些空字符是代表圖片的占位符,哪些是普通的空字符。使用CoreText處理點(diǎn)擊事件的關(guān)鍵是判斷點(diǎn)擊的位置是本文內(nèi)容中的第幾個(gè)字符,然后通過(guò)判斷該字符是否在需要處理點(diǎn)擊事件的字符串范圍內(nèi)。
*/