IOS 使用CoreText實現表情文本URL等混合顯示控件

實現了一個富文本視圖控件。主要針對表情圖片,文本字符,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

這種類型字符串的方法。那麼@就獲得了支持。具體細節。看源碼吧。

相關文章
相關標籤/搜索