androidhtml富文本
① 如何實現一個 Android 端的富文本編輯器
在 Android 上實現富文本編輯器的思路大致分為三種:
使用多種 Layout 布局,每一種布局對應一種 HTML 格式,比如圖片,比如順序列表等。具體的實現例子可以參考這個鏈接。 Medium 和
Evernote 的富文本編輯就是採用這種方式實現的。總體來說比較復雜。
WebView + JavaScript 實現。現在 Web 端有很多成熟的 JavaScript 富文本編輯庫,比如 Squire ,你只需要做好
WebView 和 JavaScript 的交互就可以了(多寫回調函數)。理論上雖然是這么說,但是在實現過程你需要解決 WebView 的兼容性問題(
Android 4.4 及其以上版本和 4.4 以下版本的 WebView 內核不一樣),以及其他一些不可預見的問題(比如就遇到無法粘貼文字的問題)。
EditText + Span 。 Android 的 TextView 原生支持諸如粗體、刪除線、引用等 Span
,要實現簡單的富文本編輯需求,可操作性還是比較大的。綜合再三,選擇了這種方式來實現自己的需求。
既然決定使用 EditText + Span 的方式來實現,必然要對相關的 API 有所了解。
首先來了解一下 Span 。Span 是一個強大的概念,有興趣深入的同學推薦直接閱讀這篇譯文。
在這里主要使用兩種類型的 Span :
繼承自 CharacterStyle 的 Span ,比如 StyleSpan ,可以在字元級別上添加粗體,下劃線等。
繼承自 ParagraphStyle 的 Span ,比如 QuoteSpan ,可以為段落級別的文本添加引用。
接著需要一個可以將 Span 的效果設置進去的文本結構(即實現了 Spannable 介面), SpannableStringBuilder
是個不錯的選擇,同時 EditText 提供的 getEditableText() 方法也可以獲得。通常只需要 getEditableText()
就可以了,但是在面對一些細節部分,可以使用 SpannableStringBuilder 預先設置相應的 Span ,再替換到原來的文本中。
設置 Span 的方式也很簡單,需要調用 Spannable.setSpan(Object what, int start, int end, int
flags) 這個方法即可,方法中 4 個參數的解釋如下:
Object what ,傳入你使用的 Span 對象。
int start ,設置 Span 的開始位置。
int end ,設置 Span 的結束位置。
int flags ,代表設置 Span 的作用域。
在這里重點介紹一下 int flags 這個參數,它接受 4 種類型的參數,分別是:
Spanned.SPAN_INCLUSIVE_EXCLUSIVE ,表示你在設置 Span 的區域之前輸入文字,輸入的文字也會受到 Span
的影響。
Spanned.SPAN_INCLUSIVE_INCLUSIVE ,表示你在設置 Span 的區域前後輸入文字,輸入的文字都後受到 Span
的影響。
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ,表示你在設置 Span 的區域中出輸入文字,輸入的文字才會受到 Span
的影響。
Spanned.SPAN_EXCLUSIVE_INCLUSIVE ,表示你在設置 Span 的區域之後輸入文字,輸入的文字也會受到 Span
的影響。
「受到影響」的意思就是,仍然會保持你設置的 Span 的樣式,比如選擇Spanned.SPAN_EXCLUSIVE_INCLUSIVE
設置了一段文字的粗體,那麼在這段文字後新輸入的文字,也會是粗體。在這里推薦使用Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
參數,畢竟其他幾種參數相對不是很好控制,而且會給使用的人帶來的疑惑。認為一個操作代表的行為應當是准確沒有歧義的。
好,到這里已經知道大致怎麼作出一個富文本編輯器組件的樣子了,無非是指定開始位置和結束位置,再設置相應的 Span
即可。至於設置的時候採取什麼樣的規則,你可以自己定製。但僅僅解決了編輯的問題,仍然存在導入的問題和導出的問題。
導入的問題十分簡單, Android SDK 中提供了 Html.fromHtml() 這個方法,可以很輕松地將 HTML 字元串轉換為所需的
Spanned 對象。但是需要注意的是, Html.fromHtml() 並不支持所有的 HTML 標簽,比如無序列表就不支持,因此你需要自己實現
Html.TagHandler 介面來處理自己所需的標簽,可以參考這個鏈接,實現了刪除線和簡單無序列表的支持。
面對粗體、斜體這樣字元級別的樣式, Html.fromHtml()
會自然而然的解析,該添加換行的地方就添加換行,並沒有什麼問題;但是面對引用、無序列表這樣段落級別的樣式,該方法會追加一個換行,也就是兩個換行操作,相當於多出一個空行。通常來說認為一個
對應兩個
,但是如果你有特別需求的話,也可以通過前面說的那樣,自己來解析,而不是用系統默認的方式。
之前介紹了如何導入,想必你也十分清楚,必然有一個對應的Html.toHtml() 方法!沒錯,但是遺憾的是,這個方法也不全支持所有 Span
,比如列表就不支持。不過沒有關系, Html.toHtml() 這個方法本身的源碼簡潔易懂,可以參考著實現。
在這里重點說明 Spannanle 的一個介面方法 nextSpanTransition(int start, int limit, Class
type) ,這個方法會在你指定的文本范圍內,返回下一個你指定的 Span 類型的開始位置,依照這個方法,就可以逐層掃描指定的 Span
,而不用同時考慮其他類型的 Span 的影響,十分有用。
最後盡管說了這么多,導入導出還是有一個比較關鍵的問題,即導入的內容和導出的內容要保持一致,在這點上目前我還比較難以實現,只能說盡量控制吧,必要的時候還需要使用一下正則來處理導入導出的文本。
② 有道雲筆記跨平台富文本編輯器的技術演進
有道雲筆記提供跨平台的富文本編輯能力,包括Windows、Mac OS、桌面瀏覽器(webkit內核)、iOS、Android等終端。實現這一功能的關鍵在於跨平台架構設計,核心是使用前端技術構建編輯器並在特定的宿主環境——Native App提供的瀏覽器環境——中運行。不同平台使用的瀏覽器環境如下:
在Windows平台,客戶端使用CEF(Chromium Embedded Framework)作為瀏覽器環境,它基於Chromium內核,支持跨Windows/Mac/Linux桌面平台,性能好,支持HTML5/CSS3等新特性。Android 4.0+ 中,有道雲筆記使用了CrossWalk提供瀏覽器環境,旨在為Android 4.0+系統提供一個一致的性能強勁的WebView。然而,由於系統不斷更新迭代,系統自帶的WebView已使用Chromium內核,CrossWalk的優勢在高版本Android中不明顯。因此,在Android 7.0+中,使用了系統自帶的WebView。
編輯器的迭代與設計選擇主要圍繞宿主環境的選擇、內容編輯特性的實現和持久存儲層的設計。早期版本的編輯器基於簡單網頁交互形式實現基本文本編輯,而隨著技術發展,引入了瀏覽器的contenteditable特性,這使得編輯器能夠實現更強大的富文本編輯功能。然而,contenteditable特性存在兼容性問題及瀏覽器間差異,因此在後續版本中,團隊選擇採用XML對數據及格式進行嚴格定義,分離數據層和視圖層,實現更可控的編輯器功能。
第三代編輯器基於XML定義存儲層,使用HTML內容與Range快照實現undo/redo功能,並對輸入的HTML內容進行過濾處理,以確保數據的正確性和一致性。同時,編輯器與Native App的通信更加緊密,提供了一系列介面以訪問設備功能,如持久存儲、相冊相機和震動器,從而實現更豐富和可靠的功能。
超越contenteditable的編輯器實現則涉及到XML定義數據層、分離數據層與視圖層、實現細粒度的undo/redo機制、以及應對協同編輯需求。這一過程涉及從數據結構到命令執行、再到視圖更新的全面設計,旨在提供更高效、更靈活的編輯體驗。
總之,有道雲筆記的富文本編輯器通過跨平台架構設計、迭代優化以及對內容處理機制的深入探索,實現了在不同終端上提供一致且強大的編輯能力,為用戶提供了便捷和高效的筆記編輯體驗。
③ html移動端(微信)開發input輸入框兼容性問題
文本框是網頁開發中常見的一種輸入控制項,用於用戶輸入文本信息。它的功能和特性多種多樣,包括可增長或固定高度、垂直或水平溢出、支持單行或多行輸入、表情符號支持、富文本編輯、所見即所得模式、指令允許等。
實現一個文本框涉及到渲染、游標位置計算、用戶輸入處理等多個方面。渲染方面,需要根據輸入的字元集合,將其正確顯示在界面上。游標位置計算涉及到字元間的間距和屏幕尺寸,以確定游標應位於哪個位置。用戶輸入時,游標位置會隨之變化,實現這一功能需要精確計算。
文本框的復雜性主要體現在不同條件下的行為處理,如添加新字元、刪除字元、滑鼠操作等。例如,當達到游標位置的上限或下限時,游標位置不會改變,而是改變顯示文本的窗口。滑鼠操作如點擊和拖動也需要精確計算,以適應不同場景。
引入可變寬度字體和富文本功能增加了實現的難度。可變寬度字體要求更復雜的游標位置計算和滑鼠操作處理,以適應字體寬度的變化。而富文本功能要求對不同特性的文本部分進行精確處理和順序渲染。
深入了解文本框的實現細節,能夠幫助開發者更好地理解網頁開發中輸入控制項的工作原理。這不僅有助於在實際項目中進行優化和創新,還能夠激發開發者探索更多可能性,推動技術的發展和創新。在追求技術透明度的背景下,深入了解文本框的實現細節,能夠幫助開發者跳出已有的框架,激發創造力,探索更高效、更符合用戶需求的解決方案。
④ Android WebView 在開發過程中有哪些坑
多線程 如果在子線程中調用WebView的相關方法,而不在UI線程,則可能會出現無法預料的錯誤。 所以,當程序中需要用到多線程時候,也請使用 runOnUiThread()方法來保證關於WebView的操作是在UI線程中進行的: runOnUiThread(newRunnable(){ @Ov...
首先webview可以載入兩種:1.帶標簽的富文本;2.網頁地址。 1、載入富文本: webView.loadDataWithBaseURL(null, html, "text/html", "utf-8", null); 其中,加粗的地方是服務端返回的String類型的富文本,"text/html"是轉換類型,utf-8是編碼格...
下面說說我比較困惑的幾個地方。 1.WebViewClient.onPageFinished()。你永遠無法確定當WebView調用這個方法的時候,網頁內容是否真的載入完畢了。當前正在載入的網頁產生跳轉的時候這個方法可能會被多次調用,StackOverflow上有比較具體的解釋(...
注意4.4系統前後的區別,在這個版本裡面谷歌把webview的內核換成谷歌瀏覽器的! 在webview中進行JavaScript交互時也要注意,出於對安全性的考慮,在設置與JavaScript有關的選項時,需要在所在方法的前面加上@SuppressLint({ "JavascriptInterfac...
自Android 4.4起,引入了webView,使用需要注意的事項: 1.多線程 如果你在子線程中調用WebView的相關方法,而不在UI線程,則可能會出現無法預料的錯誤。 所以,當你的程序中需要用到多線程時候,也請使用 runOnUiThread()方法來保證你關於WebVi...
Android開發需要注意的幾項: 1、導入的類庫需要和項目在同級目錄下,謹防資源文件與類庫中沖突。 2、textviewsetText為int時候,textview的color代碼設置,set/getTextSize 單位問題。 3、json 屬性節點不能有空格。 4、asset下使用第三方字體 ...
自Android 4.4起,引入了webView,使用需要注意的事項: 1.多線程 如果在子線程中調用WebView的相關方法,而不在UI線程,則可能會出現無法預料的錯誤。