自訂文字編輯器是非 EditText
元件或 WebView
文字小工具的檢視畫面,但都無法藉由實作 onCreateInputConnection()
回呼來支援文字輸入。系統會在聚焦檢視畫面時呼叫此回呼,讓系統為檢視畫面要求 InputConnection
。
從自訂文字編輯器呼叫 onCheckIsTextEditor()
時應傳回 true
。
支援自訂文字編輯器中的觸控筆手寫功能
根據預設,Android 14 (API 級別 34) 以上版本支援標準 Android 文字輸入元件中的觸控筆輸入功能 (請參閱「文字欄位中的觸控筆輸入內容」)。但自訂文字輸入欄位 (或編輯器) 需要額外開發。
如要建立自訂文字編輯器,請執行下列步驟:
- 啟用手寫功能
- 宣告手寫支援
- 支援手寫手勢 (選取、刪除、插入等)
- 將遊標位置和其他位置資料提供給輸入法編輯器
- 顯示觸控筆手寫懸停圖示
啟用手寫功能
如果檢視畫面只包含單一文字編輯器,檢視畫面系統可以自動為該檢視畫面啟動觸控筆手寫功能。否則,檢視畫面必須實作自己的手寫啟動邏輯。
自動啟動手寫輸入功能
如果檢視畫面顯示單一文字編輯器,但沒有其他內容,檢視畫面可以呼叫 setAutoHandwritingEnabled(true)
,選擇在檢視畫面系統自動進行手寫輸入。
啟用自動手寫功能後,從檢視畫面手寫邊界的任何位置開始,觸控筆動作就會自動啟動手寫模式。輸入法編輯器 (IME) 會接收觸控筆動作事件,並提交已辨識的文字。
自訂手寫功能
如果檢視畫面除了單一文字編輯器以外,還包含多個文字編輯器或內容,檢視畫面必須按照下列方式實作自己的手寫啟動邏輯:
呼叫
setAutoHandwritingEnabled(false)
,關閉檢視畫面系統的自動手寫功能啟動功能。追蹤在檢視畫面中顯示的所有文字編輯器。
監控
dispatchTouchEvent()
中檢視畫面接收的動作事件。如果觸控筆動作發生在文字編輯器的手寫邊界內,請將焦點移至文字編輯器 (如果尚未聚焦)。
如果編輯器尚未聚焦,請呼叫
InputMethodManager#restartInput()
,以新內容重新啟動編輯器的 IME。呼叫
InputMethodManager#startStylusHandwriting()
,啟動觸控筆手寫工作階段。
如果文字編輯器位於可捲動的檢視畫面中,請將編輯器手寫範圍中的觸控筆移動視為手寫輸入,而非捲動。使用 ViewParent#requestDisallowInterceptTouchEvent()
可避免可捲動的祖系檢視畫面攔截文字編輯器的觸控事件。
API 詳細資料
MotionEvent#getToolType()
— 指出MotionEvent
是否來自觸控筆,在這種情況下,回傳值為TOOL_TYPE_STYLUS
或TOOL_TYPE_ERASER
。InputMethodManager#isStylusHandwritingAvailable()
— 指出輸入法編輯器是否支援觸控筆手寫。由於手寫可用性可能已經變更,因此每次呼叫InputMethodManager#startStylusHandwriting()
前,都應呼叫這個方法。InputMethodManager#startStylusHandwriting()
:讓輸入法編輯器進入手寫模式。系統會將ACTION_CANCEL
動作事件分派給應用程式,以取消目前的手勢。系統不再將觸控筆動作事件分派給應用程式。對於已分派至應用程式的目前手勢,觸控筆動作事件會轉送到 IME。必須提供 IME,以便顯示觸控筆墨水視窗,輸入法編輯器接收以下所有
MotionEvent
物件。IME 修訂版本會使用InputConnection
API 辨識手寫文字。如果 IME 無法進入手寫模式,這個方法呼叫便為免人工管理。
宣告手寫支援
填入 View#onCreateInputConnection(EditorInfo)
的 EditorInfo
引數時呼叫 setStylusHandwritingEnabled()
,通知 IME 文字編輯器支援手寫功能。使用 setSupportedHandwritingGestures()
和 setSupportedHandwritingGesturePreviews()
宣告支援的手勢。
支援手寫手勢
IME 可以支援多種手寫手勢,例如透過旋轉文字選取該手勢,或透過塗鴉的方式刪除文字即可刪除手勢。
自訂編輯器會實作 InputConnection#performHandwritingGesture()
和 InputConnection#previewHandwritingGesture()
來支援不同的 HandwritingGesture
類型,例如 SelectGesture
、DeleteGesture
和 InsertGesture
。
在填入 View#onCreateInputConnection(EditorInfo)
的 EditorInfo
引數時,宣告支援的手寫手勢 (請參閱「宣告手寫支援」一節)。
API 詳細資料
InputConnection#performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)
:實作手勢。HandwritingGesture
引數包含位置資訊,可用來判斷文字中的位置,以便執行手勢。舉例來說,SelectGesture
提供RectF
物件來指定所選文字範圍,InsertGesture
提供PointF
物件,用於指定文字偏移位置。使用
Executor
和IntConsumer
參數,傳回作業結果。如果同時提供執行程式和消費端引數,請使用執行程式呼叫IntConsumer#accept()
,例如:executor.execute { consumer.accept(HANDWRITING_GESTURE_RESULT_SUCCESS) }
HandwritingGesture#getFallbackText()
:如果手寫手勢區域下方沒有任何適用文字,系統會於遊標位置提供 IME 修訂版本的備用文字。有時 IME 無法判斷觸控筆手勢是否用於執行手勢作業或手寫文字。自訂文字編輯器負責判斷使用者的意圖,並在手勢位置採取適當動作 (視情境而定)。
舉例來說,如果輸入法編輯器無法確定使用者是否打算繪製向下插入空格 ⋁,執行插入空格手勢或手寫字母「v」,則輸入法編輯器可以傳送含有備用文字「v」的
InsertGesture
。編輯器應先嘗試執行插入空格手勢。如果無法執行手勢 (例如,指定位置沒有任何文字),編輯器應改回在遊標位置插入「v」。
InputConnection#previewHandwritingGesture(PreviewableHandwritingGesture, CancellationSignal)
:預覽進行中的手勢。舉例來說,當使用者開始在某段文字周圍繪製圓形時,系統會在使用者繼續繪圖時,顯示即時預覽結果預覽並持續更新。只有特定手勢類型可供預覽 (請參閱PreviewableHandwritingGesture
)。IME 可使用
CancellationSignal
參數取消預覽。如果其他事件導致預覽作業中斷 (例如以程式輔助方式變更文字,或出現新的InputConnection
指令),自訂編輯器可能會取消預覽。預覽手勢僅供顯示,不應變更編輯器的狀態。舉例來說,
SelectGesture
預覽會隱藏編輯器目前的選取範圍,並醒目顯示手勢預覽範圍。不過,一旦取消預覽,編輯器就應還原先前的選取範圍。
提供遊標位置和其他位置資料
在手寫模式中,輸入法編輯器可以使用 InputConnection#requestCursorUpdates()
要求遊標位置和其他位置資料。自訂編輯器會呼叫 InputMethodManager#updateCursorAnchorInfo(View,
CursorAnchorInfo)
。與觸控筆手寫相關的 CursorAnchorInfo
資料會透過下列 CursorAnchorInfo.Builder
方法提供:
setInsertionMarkerLocation()
:設定遊標位置。IME 會使用這個值,為手寫墨水建立動畫效果至遊標位置。setEditorBoundsInfo()
:設定編輯器的邊界和手寫邊界。IME 會使用這項資料,將輸入法編輯器的手寫工具列放在螢幕上。addVisibleLineBounds()
:設定編輯器所有可見 (或部分顯示) 文字行的邊界。IME 會使用線條邊界來改善辨識手寫手勢的準確度。setTextAppearanceInfo()
:使用衍生文字輸入欄位的資訊,設定文字外觀。輸入法編輯器會根據這項資訊設定手寫手寫樣式的樣式。
顯示觸控筆手寫懸停圖示
當觸控筆懸停在自訂文字編輯器的手寫範圍上,且所選的輸入法編輯器支援觸控筆手寫時,即可顯示觸控筆手寫懸停圖示 (InputMethodManager#isStylusHandwritingAvailable()
)。
覆寫 View#onResolvePointerIcon()
,取得觸控筆手寫的懸停圖示。在覆寫中,呼叫 PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING)
即可存取系統觸控筆手寫懸停圖示。