RichEditor——一款基于RecyclerView實現(xiàn)的富文本編輯器實現(xiàn)方案(支持圖文、轉(zhuǎn)義生成MarkDown、粗體、斜體、下劃線、刪除線、超鏈接、標題等)

前言

對于富文本編輯器的實現(xiàn),首先我們肯定會想到實現(xiàn)的編輯器需要支持的幾個必要特性:

1.涉及大量文字,圖片,文字樣式的展示與編輯。
2.涉及極其復雜的用戶交互。

目前Github上我所了解的富文本編輯器基本上實現(xiàn)方式基于兩種:

  • 1.基于WebView拓展的富文本編輯器。
  • 2.基于EditText重寫的富文本編輯器。

對于這兩種方案,這里提出一些我個人的看法。

1.WebView實現(xiàn)

首先WebView的渲染性能一個弊端所在,其次當涉及極其復雜的人機交互,WebView的實現(xiàn)起來就會比較困難。還有一點就是WebView的兼容性也是一個需要考慮的一點。

2.EditText重寫

對于重寫單個EditText,確實對于交互和文字渲染,樣式支持,都有很強的拓展性。但是考慮到會存在大量的圖片,這里就需要考慮到內(nèi)存的情況,對于EditText來說,肯定不存在View的復用,基本上有多少圖片,就要多少內(nèi)存。另一方面原生的TextView對于大量文字的渲染一直被人詬病,對此也有很多對于TextView的性能優(yōu)化的方案。

RecyclerView實現(xiàn)

所以我最終選擇使用RecyclerView作為實現(xiàn)富文本編輯器的實現(xiàn)方案。雖然有坑,但是也是一種可行性方案。(豆瓣的編輯器就是使用RecyclerView實現(xiàn))
優(yōu)點:首先RecyclerVie作為一款原生組件,對于大量UI組件的展示有非常良好的性能,其次RecyclerView的復用機制對于內(nèi)存消耗的控制提供了的很好的支持。
缺點::當然這里也不是說RecyclerView就絕對是實現(xiàn)富文本編輯器的首選方案,我在實現(xiàn)的過程中也遇到了很多大坑,這里就隨便列舉幾個:
1.焦點的控制
2.數(shù)據(jù)的拼接
3.樣式的存儲
4.光標的位置
and much more...
還好最后這些坑也找到了解決方案,所以這里分享一下這種實現(xiàn)方案,也為有需求的人提供一種可做參考的實現(xiàn)方案吧。

已實現(xiàn)功能

1.文本的粗體、斜體、下劃線、中劃線、刪除線、超鏈接、引用樣式、H1、H2、H3、H4。
2.圖片的插入和刪除
3.選中文本實時更改樣式
4.任意位置換行保持樣式。
5.兩行刪除為一行保持樣式。
6.隨光標實時顯示文字樣式到控制面板。
7.任意位置插入樣式
8.最終編輯文本轉(zhuǎn)MarkDown(有Bug~。。。。)
等。。。

實現(xiàn)效果

效果圖

樣式拼接

對于RecyclerView實現(xiàn)而言,回車對應的操作就是增加一個Model,所以回車換行和刪除就需要做非常多的邏輯情況處理,并且還涉及到樣式索引的拼接和分割,總之是一個大坑。

樣式選中修改

選中后,需要對光標,樣式的索引,樣式的清除和分割,還有樣式的重新創(chuàng)建和賦值,大坑啊大坑。

樣式同步

光標對應到對應樣式的字符串時,下面的面板對應實時更改當前樣式,需要利用區(qū)間的邏輯判斷,對光標和樣式區(qū)間進行邏輯判斷,坑越來越多。。。

還有許多復雜的交互處理,這里沒有展示,具體大家可以查看源碼。

項目地址

RichEditor

使用方式

這里并沒有將工程發(fā)布到JitPack,因為作為一款富文本編輯器,每人都有自己獨特的需求和交互方式,沒辦法做到一個富文本能夠應付所有的需求。并且由于富文本編輯器的交互邏輯確實復雜,沒辦法保證兼容到所有到交互和情況,所以這里只是盡自己可能實現(xiàn)到交互情況。

1.引入editor的lib到工程
2.xml加入編輯器

<com.study.xuan.editor.widget.Editor
        android:id="@+id/editor"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

就可以正常使用了。

進階

簡單到封裝了一下使用利用RichHelper

//綁定xml中的Editor
public void attach(Editor editor);
//new 一個Editor
public Editor buildEditor(Context context)
//部分事件回調(diào)
public void setCallBack(onEditorEventListener callBack)
//操作面板右側(cè)空白增加自定義布局
public void setMoreOperateLayout(View view)
//異步轉(zhuǎn)義MarkDown
public void toMarkDown()
public interface onEditorCallback { 
    //行數(shù)量變化時
    void onLineNumChange(List<RichModel> data);
    //點擊操作面板的圖片添加圖片,可以使用自己項目中的圖片框架,選中后對應調(diào)用editor.addPhoto(List<String> data);方法即可
    void onPhotoEvent();
    //轉(zhuǎn)義MarkDown的進度回調(diào)
    void onMarkDownTaskDoing(int progress, int max);
    //轉(zhuǎn)義MarkDown成功
    void onMarkDownTaskFinished(String markdown);
}

架構(gòu)圖

架構(gòu)圖

1.RichBuilder

全局單例,底層架構(gòu),幫助RichEditor整體的功能實現(xiàn)。

1.1 IPanel

實現(xiàn)類PanelBuilder包含兩個實現(xiàn)類,F(xiàn)ontParamBuilder表示字符類型的樣式,ParagraphBuilder表示段落類型的樣式。Panle和Editor的通信方式是通過底層的RichBuilder單例中的IPanel。

1.2 IAbstractFactory

抽象工程類,用于外層對span類型的創(chuàng)建。其中抽象工廠又分為ICharacterStyleFactory,IParagraphFactory,IUpdateAppearanceFactory三種span工廠,分別對應CharacterFactory(字符樣式span工廠),ParagraphFactory(段落樣式工廠),(自定義工廠未實現(xiàn))。

1.3 ISearchStrategy

搜索策略,用于對于某一段落中的span樣式的遍歷和處理,其中NormalSearch實現(xiàn)ISearchStrategy,利用常規(guī)遍歷處理(可以自定義實現(xiàn)快排或其他效率高的排序方式進行處理)

1.4 IParamManager

參數(shù)管理接口,實現(xiàn)類對應ParamManager,用于對當前樣式和預輸入樣式的對比和處理。

2.Editor

編輯器實現(xiàn)類,繼承于RecyclerView,Adapter對應RichAdapter,Model對應RichModel。

2.1 ISpanFilter

輸入過濾器,用于對輸入和刪除時的樣式處理。
SpanStep1Filter
第一級過濾器,用于處理樣式的追加和混雜時,對于SPAN_EXCLUSIVE_INCLUSIVESPAN_EXCLUSIVE_EXCLUSIVE的處理。
SpanStep2Filter
第二級過濾器,用于處理樣式的創(chuàng)建和保持,用于獲取當前文本所有的樣式集,并記錄樣式對應的index,保持到對應的RichModel中。

2.2 ParseAsyncTask

異步處理,用于處理將數(shù)據(jù)轉(zhuǎn)換成對應的轉(zhuǎn)換類型。
Parse
轉(zhuǎn)換接口
MarkDownParse
轉(zhuǎn)為MarkDown語法的邏輯處理,利用正則表達式。

2.3 RichModelHelper

數(shù)據(jù)處理類,用與合并樣式,處理樣式等相關(guān)的數(shù)據(jù)處理。

3.Panel

Panel表示操作面板,Panel默認使用的是EditorPanelAlpha。Panel通過RichBuilder中的IPanel實現(xiàn)和編輯器Editor的聯(lián)動。

總結(jié)

實現(xiàn)到過程中本來以為非常容易,結(jié)果實現(xiàn)到過程中發(fā)現(xiàn)坑越來越多,越來越大,但總算是將遇到的坑都找到了解決方案,從去年年底到上個月,前前后后大概開發(fā)了小半年,90多次commit也算是為大家踩踩坑,我認為以RecyclerView作為基礎(chǔ)組件開發(fā)富文本編輯器,它在性能上到優(yōu)勢,和原生到體驗,可以作為一種可行性方案作為參考依據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容