實現了一個富文本視圖控件。主要針對表情圖片,文本字符,URL,等這種類型的文本進行顯示。git
源碼地址 https://github.com/TinyQ/TQRichTextView 實現的效果以下圖。程序員
控件展現完畢 github
---------------------------------------------------------------------------------------------------算法
這裏先介紹下我寫這個控件的項目目錄結構和功能。從下面這個目錄結構截圖提及。數組
1.EmojiLmage 文件夾存放的是表情圖片資源。學習
2.TQRichTextBaseRun 這個是特殊文本元素的抽象對象。這裏定義了須要子類實現方法和屬性。URLRun,ImageRun 等都是從這個繼承。url
3.TQRichTextURLRun 這個是用來支持URL文本類型的文本元素對象。spa
4.TQRichTextImageRun 這個是圖片類型的文本元素對象。好比表情文本實際上是要繪製圖片到文本中間。後面的EmojiRun就是派生自這個對象。code
5.TQRichTextEmojiRun 這個是表情文本元素對象,用來識別表情字符串替換成表情圖片工做。orm
6.TQRichTextView 文本顯示所用到的視圖。
這裏先簡要說一下這個控件的工做流程。
1.首先。確定是咱們會得到一個要現實的文本字符串。 好比是下面這樣的。(舉例)
「這裏是面向程序員的知識分享與學習社區[呵呵][憤怒]不容許發佈任何推廣、廣告、政治方面的https://github.com/TinyQ/TQRichTextView內容」
2.咱們須要對這個字符串進行解析。以便剝離出哪些是文本,表情。url。而後文本的話就是普通顯示,表情就替換成對應的圖片。URL就藍色高亮顯示。
咱們解析出來的就是這樣的。按照下面的順序。
「這裏是面向程序員的知識分享與學習社區
TQRichTextEmojiRun(呵呵) 標記位置是 Rect(18,4)
TQRichTextEmojiRun(憤怒) 標記位置是 Rect(22,4)
不容許發佈任何推廣、廣告、政治方面的
TQRichTextURLRun 標記位置是 Rect(xx,xx) 我就不數數查了。囧
內容」
3.繪製。其實CoreText的繪製方式是這樣的。它能夠將文本所有給CoreText,而後它會給你繪製好。包括換行等。你只須要在表情的地方流出空白,而後在繪製上圖片
就能夠了,(但其實這個控件裏面換行也是本身計算的。由於發現會有行間距不一致的bug,表情在行爲換行不對的bug等。用coretext自動繪製的話)。
在這個項目裏。簡單根據代碼說下具體實現
//-- 解析文本內容 - (NSString *)analyzeText:(NSString *)string { [self.richTextRunsArray removeAllObjects]; [self.richTextRunRectDic removeAllObjects]; NSString *result = @""; NSMutableArray *array = self.richTextRunsArray; result = [TQRichTextEmojiRun analyzeText:string runsArray:&array]; result = [TQRichTextURLRun analyzeText:result runsArray:&array]; [self.richTextRunsArray makeObjectsPerformSelector:@selector(setOriginalFont:) withObject:self.font]; return result; }
獲得文本後,咱們對文本進行解析。具體解析算法呢,都是寫在對應的RichTextxxxRun中的。
好比表情解析就是在TQRichTextEmojiRun 中。url同理。在解析的過程當中,好比解析表情。
匹配到了表情,就生成一個TQRichTextEmojiRun 對象,這個對象記錄了這個表情文本的位置。
原始字符等信息。把根據生成的對象放入richTextRunsArray這麼一個數組中。用於文字渲染完後根據
這個對象渲染表情圖片。由於都是繼承baseRun來的。因此,解析出來的無論是表情,仍是url什麼,都會
統一執行渲染方法。
當咱們解析完,獲得了特殊文本的run數組對象。咱們就繪製文本。而後填補表情等。這些就是在 drawRect
這個方法裏面執行的了。我就不貼了。比較長。也比較多。
這裏在說明下BaseRun 裏面抽象的2個方法
//-- 替換基礎文本 - (void)replaceTextWithAttributedString:(NSMutableAttributedString*) attributedString { [attributedString addAttribute:@"TQRichTextAttribute" value:self range:self.range]; } //-- 繪製內容 - (BOOL)drawRunWithRect:(CGRect)rect { return NO; }
1.replaceTextWithAttributedString 這個方法,是用來替換文本的。說是替換,其實有2中狀況。
若是文本單元是一個表情的話。我須要將原先的字符串用一個空格代替 ,而後預留出畫表情的位置。繪製表情圖片在圖層
在好比文本單元是一個URL的話。其實這裏沒有替換之前的URL,只是設置了屬性字符串。在URL這一段,讓他藍色顯示。
2.drawRunWithRect
這個方法是繪製文本單元。和上面相似。若是表情文本單元,這個就要負責回事圖片到圖層。若是是URL,這個方法直接返回
NO 就行了。告訴繪製的時候。這個方法什麼都沒有作。(這跟後面作觸摸響應時間時候。得到正確的點擊區域判斷有關係。)
這裏我舉個例子。好比你用這個控件。你說你不單單要實現URL,表情,你要加一個@XXX 要能夠點擊。也要綠色顯示。
那你就能夠繼承TQRichTextBaseRun 實現一個TQRichTextAtRun。實現這2個方法。能夠參照URLRun。而後在加入解析@xxx
這種類型字符串的方法。那麼@就獲得了支持。具體細節。看源碼吧。