談談移動端富文本
Android端的富文本實現主要有兩個大的分支
- 基於WebView的渲染
- 基於TextView/EditText的渲染
而且他們都有一個共同點,需要解決不同版本的Android甚至是不同廠家的ROM的適配問題。
首先考察WebView方案,這是一種工程性價比比較高的解決方案,一套Js富文本引擎可以兼容PC/Android/iOS/Web APP甚至Win10 UWP,而且也有比較多的開源富文本引擎可以參考,但是這套方案運行於WebView之中,跨平台特性也強烈依賴WebView在不同平台的一致性。[NONo筆記]只兼容Android4.0+,但這還遠遠不夠!Android4.4以下的原生WebView差異性非常大,而且4.0.3/4、4.2.2的原生WebView性能堪憂,很難帶來絲滑的編輯體驗。要解決這個問題,通用的解決方案是在APP內嵌入一個chromium內核,這個內核足足有16MB!
我的目標是儘力將整個應用控制在10MB以下,甚至未來壓縮到8MB以下!最終只能忍痛放棄WebView方案。
考慮到我的富文本選項
- 字型大小
- 下劃線
- 刪除線
- 粗體、斜體
- 上標、下標
- 前景著色、後景著色
- 圖片
- 數字列表、點號列表
使用基於TextView/EditText的渲染,也就是Android的Span,足以應付這些選項,圖片、列表無非是手寫兩個TagHandler。
但是,在發布兩天後就迎來了第一個災難性的問題,當用戶編輯一長段文字後,再回到前面插入字元時,卡頓現象非常明顯,而且這是EditView顯示Spannable對象避免不了的問題!不過,更可怕的是很多個性化的編輯體驗也很難拓展,比如如果想在圖片上加一些注釋或自定義的點綴效果,開發和維護成本將會指數式上升,因為這種個性化的效果只靠Html的表達力是很難勝任的,必然要引入CSS和Js,Androi的原生Html只支持Html標籤和屬性(Attribute),這就意味我需要人肉進行[CSS+Js]<->[Html+Attribute]的雙向解析和生成!我們來體驗一段最簡單的Html屬性解析代碼吧:
Field elementField = null;n try {n elementField = xmlReader.getClass().getDeclaredField("theNewElement");n elementField.setAccessible(true);n Object element = elementField.get(xmlReader);n Field attsField = element.getClass().getDeclaredField("theAtts");n attsField.setAccessible(true);n Object atts = attsField.get(element);n Field dataField = atts.getClass().getDeclaredField("data");n dataField.setAccessible(true);n String[] data = (String[])dataField.get(atts);n Field lengthField = atts.getClass().getDeclaredField("length");n lengthField.setAccessible(true);n int length = (Integer)lengthField.get(atts);n fontSize = data[4];n float scaleDensity=context.getResources().getDisplayMetrics().scaledDensity;n if(fontSize.contentEquals("small")) {n output.setSpan(new RelativeSizeSpan(0.75f), len, len, Spannable.SPAN_MARK_MARK);n }else if(fontSize.contentEquals("large")){n output.setSpan(new RelativeSizeSpan(1.25f), len, len, Spannable.SPAN_MARK_MARK);n }else {n output.setSpan(new RelativeSizeSpan(1.0f), len, len, Spannable.SPAN_MARK_MARK);n }n } catch (NoSuchFieldException e) {n e.printStackTrace();n } catch (IllegalAccessException e) {n e.printStackTrace();n }n
不要問我為什麼需要這樣,看這裡!
前面發生的這些讓我下定決心繼續探究Android端富文本的簡潔實現。
無意中在GitHub上看到這個項目:GitHub - xmuSistone/android-animate-RichEditor: android rich text editor which enables users to insert/delete bitmaps and text into edit-view with animations.,可以進行圖文混排,而且圖片具有一定的動畫效果。
思路是,整個富文本控制項用LinearLayout來實現,其他的富文本組件作為子控制項!這樣做的優點不言而喻。
- 後期拓展非常方便,不必陷入長長的TextWatcher代碼中,很難進行多人協同維護。
- 支持效果無限可能,圖片顯示可以用原生的ImageView,動畫特效可以用FrameLayout+View Animator,總之,它就是原生布局,能做到的效果無限多。
- 性能優化方案更多,原生的View優化方案都可以用上來,比如我們以後可以用RecycleView做根View,甚至自己模仿RecycleView寫一個更適合的ViewGroup,通過這些方案來進行內存佔用優化。
- 編輯體驗更加流暢,通過將長的EditText分成多個EditText,性能瓶頸瞬間得到突破!
歡迎大家體驗:NONo筆記
推薦閱讀: