Benutzerdefinierte Texteditoren sind Ansichten, die keine EditText
-Komponenten oder WebView
-Textwidgets sind, aber Texteingabe unterstützen. Dazu implementieren Sie den onCreateInputConnection()
-Callback, der aufgerufen wird, wenn eine Ansicht hervorgehoben wird und das System ein InputConnection
für die Ansicht anfordert.
Bei einem Aufruf von onCheckIsTextEditor()
von einem benutzerdefinierten Texteditor sollte true
zurückgegeben werden.
In benutzerdefinierten Texteditoren wird das Schreiben mit Eingabestift unterstützt
Android 14 (API-Level 34) und höher unterstützen standardmäßig die Eingabe eines Eingabestifts in standardmäßigen Android-Texteingabekomponenten (siehe Eingabestift in Textfeldern). Benutzerdefinierte Texteingabefelder (oder Editoren) erfordern jedoch eine zusätzliche Entwicklung.
So erstellen Sie einen benutzerdefinierten Texteditor:
- Initiierung per Handschrift aktivieren
- Unterstützung für handschriftliche Eingaben
- Handschriftgesten unterstützen (Auswählen, Löschen, Einfügen usw.)
- Cursorposition und andere Positionsdaten für den IME bereitstellen
- Symbol für die Handschrifteingabe mit Eingabestift anzeigen
Initiierung per Handschrift aktivieren
Besteht eine Ansicht nur aus einem einzigen Texteditor, kann das Ansichtssystem automatisch die Eingabe des Eingabestifts für die Ansicht initiieren. Andernfalls muss in der Ansicht eine eigene Logik zur Initiierung der Handschrift implementiert werden.
Automatische Aktivierung der Handschrift
Wenn in einer Ansicht ein einzelner Texteditor und kein anderer Inhalt angezeigt wird, kann in der Ansicht die automatische Handschriftinitiierung des Ansichtssystems durch Aufrufen von setAutoHandwritingEnabled(true)
aktiviert werden.
Wenn die automatische Handschrift aktiviert ist und die Eingabe des Eingabestifts an einer beliebigen Stelle innerhalb der Handschriftgrenzen der Ansicht beginnt, wird automatisch der Handschriftmodus gestartet. Der Editor für Eingabemethoden (IME) empfängt die Bewegungsereignisse des Eingabestifts und führt den erkannten Text aus.
Benutzerdefinierte Handschrifterstellung
Wenn eine Ansicht neben einem Texteditor mehrere Texteditoren oder Inhalte enthält, muss in der Ansicht eine eigene Logik zum Initiieren der Handschrift implementiert werden:
Deaktivieren Sie die automatische Auslösung der Handschrift durch das Ansichtssystem, indem Sie
setAutoHandwritingEnabled(false)
aufrufen.Behalten Sie den Überblick über alle Texteditoren, die in der Ansicht sichtbar sind.
Mit der Ansicht in
dispatchTouchEvent()
empfangene Bewegungsereignisse werden überwacht.Wenn die Bewegung des Eingabestifts innerhalb der Handschriftgrenzen eines Texteditors erfolgt, fokussieren Sie den Texteditor (falls nicht bereits fokussiert).
Wenn der Editor noch nicht im Fokus war, starten Sie den IME des Editors mit neuen Inhalten neu. Rufen Sie dazu
InputMethodManager#restartInput()
auf.Starten Sie die Eingabestift-Handschrift, indem Sie
InputMethodManager#startStylusHandwriting()
aufrufen.
Wenn sich ein Texteditor innerhalb einer scrollbaren Ansicht befindet, sollte die Bewegung des Eingabestifts innerhalb der Handschriftgrenzen des Editors als Handschrift und nicht als Scrollen angesehen werden. Mit ViewParent#requestDisallowInterceptTouchEvent()
verhindern Sie, dass eine scrollbare Ancestor-Ansicht Touchereignisse von einem Texteditor abfängt.
API-Details
MotionEvent#getToolType()
: Gibt an, ob derMotionEvent
von einem Eingabestift stammt. In diesem Fall ist der RückgabewertTOOL_TYPE_STYLUS
oderTOOL_TYPE_ERASER
.InputMethodManager#isStylusHandwritingAvailable()
: Gibt an, ob der IME die Handschrift mit Eingabestiften unterstützt. Rufen Sie diese Methode vor jedem Aufruf vonInputMethodManager#startStylusHandwriting()
auf, da sich die Verfügbarkeit der Handschrift möglicherweise geändert hat.InputMethodManager#startStylusHandwriting()
: Der IME wechselt in den Handschriftmodus. EinACTION_CANCEL
-Bewegungsereignis wird an die App gesendet, um die aktuelle Geste abzubrechen. Bewegungsereignisse für Eingabestifte werden nicht mehr an die App gesendet.Bewegungsereignisse des Eingabestifts der aktuellen Geste, die bereits an die App gesendet wurden, werden an den IME weitergeleitet. Der IME ist erforderlich, um ein Eingabestiftfenster anzuzeigen, über das der IME alle folgenden
MotionEvent
-Objekte empfängt. Der IME führt mithilfe derInputConnection
APIs erkannten handschriftlichen Text aus.Wenn der IME nicht in den Handschriftmodus wechseln kann, ist dieser Methodenaufruf kein Vorgang.
Unterstützung für handschriftliche Eingaben
Wenn Sie das Argument EditorInfo
von View#onCreateInputConnection(EditorInfo)
eingeben, rufen Sie setStylusHandwritingEnabled()
auf, um den IME darüber zu informieren, dass der Texteditor Handschrift unterstützt.
Deklarieren Sie unterstützte Touch-Gesten mit setSupportedHandwritingGestures()
und setSupportedHandwritingGesturePreviews()
.
Handschriftgesten unterstützen
IMEs können verschiedene handschriftliche Touch-Gesten unterstützen, z. B. umkreisenden Text zum Auswählen oder Kritzeln über Text, um ihn zu löschen.
Benutzerdefinierte Editoren implementieren InputConnection#performHandwritingGesture()
und InputConnection#previewHandwritingGesture()
, um verschiedene HandwritingGesture
-Typen wie SelectGesture
, DeleteGesture
und InsertGesture
zu unterstützen.
Deklarieren Sie unterstützte Handschriftgesten, wenn Sie das Argument EditorInfo
von View#onCreateInputConnection(EditorInfo)
ausfüllen. Weitere Informationen finden Sie im Abschnitt Unterstützung für Handschrift deklarieren.
API-Details
InputConnection#performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)
: Implementiert Touch-Gesten. Das ArgumentHandwritingGesture
enthält Standortinformationen, mit denen Sie bestimmen können, an welcher Stelle im Text die Geste ausgeführt werden soll. Beispielsweise stelltSelectGesture
einRectF
-Objekt bereit, das den ausgewählten Textbereich angibt, undInsertGesture
stellt einPointF
-Objekt bereit, das den Textversatz angibt, bei dem Text eingefügt werden soll.Verwenden Sie die Parameter
Executor
undIntConsumer
, um das Ergebnis des Vorgangs zurückzusenden. Wenn sowohl das Executor- als auch das Consumer-Argument angegeben ist, verwenden Sie den Executor, umIntConsumer#accept()
aufzurufen. Beispiel:executor.execute { consumer.accept(HANDWRITING_GESTURE_RESULT_SUCCESS) }
HandwritingGesture#getFallbackText()
: Stellt einen Fallback-Text bereit, den der IME an der Cursorposition ausführt, wenn sich unter dem Bereich einer Handschriftgeste kein entsprechender Text befindet.Manchmal kann der IME nicht ermitteln, ob mit einer Eingabestiftgeste eine Geste ausgeführt oder Text per Hand geschrieben werden soll. Ein benutzerdefinierter Texteditor bestimmt die Absicht des Nutzers und führt (je nach Kontext) die entsprechende Aktion an der Bewegungsposition aus.
Wenn der IME beispielsweise nicht ermitteln kann, ob der Nutzer einen nach unten weisenden Caret ⋁ zeichnen soll, um eine Geste zum Einfügen des Leerzeichens auszuführen oder den Buchstaben „v“ von Hand zu schreiben, kann der IME ein
InsertGesture
mit dem Fallback-Text „v“ senden.Der Editor sollte zuerst versuchen, die Touch-Geste „Leerzeichen einfügen“ auszuführen. Wenn die Touch-Geste nicht ausgeführt werden kann, weil z. B. an der angegebenen Position kein Text vorhanden ist, sollte der Editor „v“ an der Cursorposition einfügen.
InputConnection#previewHandwritingGesture(PreviewableHandwritingGesture, CancellationSignal)
– Zeigt eine Vorschau einer laufenden Touch-Geste an. Wenn der Nutzer beispielsweise beginnt, einen Kreis um Text zu ziehen, kann eine Live-Vorschau der resultierenden Auswahl angezeigt und kontinuierlich aktualisiert werden, während der Nutzer mit dem Zeichnen fortfährt. Eine Vorschau ist nur für bestimmte Gestentypen verfügbar (siehePreviewableHandwritingGesture
).Der Parameter
CancellationSignal
kann vom IME verwendet werden, um die Vorschau abzubrechen. Wird die Vorschau durch andere Ereignisse unterbrochen, z. B. wenn der Text programmatisch geändert oder neueInputConnection
-Befehle ausgeführt werden, kann der benutzerdefinierte Editor die Vorschau abbrechen.Vorschaugesten dienen nur der Anzeige und sollten den Status des Editors nicht ändern. Bei der Vorschau für
SelectGesture
wird beispielsweise der aktuelle Auswahlbereich des Editors ausgeblendet und der Bereich für die Gestenvorschau hervorgehoben. Sobald die Vorschau abgebrochen wird, sollte der Editor den vorherigen Auswahlbereich wiederherstellen.
Cursorposition und andere Positionsdaten angeben
Im Handschriftmodus kann der IME die Cursorposition und andere Positionsdaten mit InputConnection#requestCursorUpdates()
anfordern.
Der benutzerdefinierte Editor antwortet mit einem Aufruf von InputMethodManager#updateCursorAnchorInfo(View,
CursorAnchorInfo)
.
Die für das Schreiben mit Eingabestiften relevanten Daten in CursorAnchorInfo
werden über die folgenden CursorAnchorInfo.Builder
-Methoden bereitgestellt:
setInsertionMarkerLocation()
: Legt die Position des Cursors fest. Der IME verwendet den Wert, um handschriftliche Tinte an der Cursorposition zu animieren.setEditorBoundsInfo()
: Legt die Grenzen des Bearbeiters und die Handschrift fest. Anhand dieser Daten positioniert der IME seine Handschriftsymbolleiste auf dem Bildschirm.addVisibleLineBounds()
: Legt die Grenzen aller sichtbaren (oder teilweise sichtbaren) Textzeilen im Editor fest. Der IME verwendet die Liniengrenzen, um die Genauigkeit der Erkennung von Handschriftgesten zu verbessern.setTextAppearanceInfo()
: Legt die Textdarstellung mit Informationen fest, die aus dem Texteingabefeld abgeleitet wurden. Der IME verwendet die Informationen, um die handschriftliche Tinte zu gestalten.
Symbol für die Handschrifteingabe mit Eingabestift anzeigen
Das Symbol für die Handschrift des Eingabestifts wird eingeblendet, wenn der Eingabestift den Mauszeiger über die Handschriftgrenze Ihres benutzerdefinierten Texteditors bewegt und der ausgewählte IME die Handschrift mit Eingabestift unterstützt (InputMethodManager#isStylusHandwritingAvailable()
).
Überschreiben Sie View#onResolvePointerIcon()
, um ein Hover-Symbol für Handschrift mit Eingabestift zu sehen. Rufen Sie in der Überschreibung PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING)
auf, um auf das Systemsymbol für die Eingabe des Eingabestifts zuzugreifen, der mit dem Mauszeiger bewegt wird.