Eingabemethode erstellen

Ein Eingabemethoden-Editor (IME) ist ein Nutzersteuerelement, mit dem Nutzer Text eingeben können. Android bietet ein erweiterbares Eingabemethoden-Framework, mit dem Anwendungen Nutzern alternative Eingabemethoden wie Bildschirmtastaturen oder Spracheingabe bereitstellen können. Nach der Installation der IMEs kann der Nutzer eine aus den Systemeinstellungen auswählen und im gesamten System verwenden. Es kann jeweils nur ein IME aktiviert werden.

Wenn Sie dem Android-System einen IME hinzufügen möchten, erstellen Sie eine Android-Anwendung mit einer Klasse, die InputMethodService erweitert. Darüber hinaus erstellen Sie normalerweise eine Aktivität „Einstellungen“, die Optionen an den IME-Dienst übergibt. Sie können auch eine Einstellungs-UI definieren, die als Teil der Systemeinstellungen angezeigt wird.

Auf dieser Seite werden folgende Themen behandelt:

Wenn Sie noch nicht mit IMEs gearbeitet haben, lesen Sie zuerst den einführenden Artikel zu Eingabemethoden auf dem Bildschirm.

IME-Lebenszyklus

Im folgenden Diagramm wird der Lebenszyklus eines IME beschrieben:

Ein Bild, das den Lebenszyklus eines IME zeigt.
Abbildung 1: Der Lebenszyklus eines IMEs.

In den folgenden Abschnitten wird beschrieben, wie Sie die UI und den Code eines IME implementieren, der diesem Lebenszyklus folgt.

IME-Komponenten im Manifest deklarieren

Im Android-System ist ein IME eine Android-Anwendung, die einen speziellen IME-Dienst enthält. In der Manifestdatei der Anwendung muss der Dienst deklariert, die erforderlichen Berechtigungen angefordert, ein Intent-Filter bereitgestellt werden, der der Aktion action.view.InputMethod entspricht, sowie Metadaten zur Definition der Eigenschaften des IMEs bereitstellen. Um eine Oberfläche für Einstellungen bereitzustellen, über die der Nutzer das Verhalten des IME ändern kann, können Sie eine Aktivität „Einstellungen“ definieren, die über die Systemeinstellungen gestartet werden kann.

Mit dem folgenden Snippet wird ein IME-Dienst deklariert. Sie fordert die Berechtigung BIND_INPUT_METHOD an, damit der Dienst den IME mit dem System verbinden kann, richtet einen Intent-Filter ein, der der Aktion android.view.InputMethod entspricht, und definiert Metadaten für den IME:

<!-- Declares the input method service. -->
<service android:name="FastInputIME"
    android:label="@string/fast_input_label"
    android:permission="android.permission.BIND_INPUT_METHOD">
    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>
    <meta-data android:name="android.view.im"
               android:resource="@xml/method" />
</service>

Im nächsten Snippet wird die Aktivität zu den Einstellungen für den IME deklariert. Sie hat einen Intent-Filter für ACTION_MAIN, der angibt, dass diese Aktivität der Haupteinstiegspunkt für die IME-Anwendung ist:

<!-- Optional: an activity for controlling the IME settings. -->
<activity android:name="FastInputIMESettings"
    android:label="@string/fast_input_settings">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>

Sie können den Zugriff auf die Einstellungen des IME auch direkt über die Benutzeroberfläche des IME gewähren.

Die Eingabemethoden-API

Spezifische Klassen für IMEs finden Sie in den Paketen android.inputmethodservice und android.view.inputmethod. Die Klasse KeyEvent ist für die Verarbeitung von Tastaturzeichen wichtig.

Der zentrale Teil eines IME ist eine Dienstkomponente – eine Klasse, die InputMethodService erweitert. Diese Klasse implementiert nicht nur den normalen Dienstlebenszyklus, sondern bietet auch Callbacks für die Bereitstellung der Benutzeroberfläche Ihres IME, die Verarbeitung von Nutzereingaben und die Übermittlung von Text an das hervorgehobene Feld. Standardmäßig bietet die Klasse InputMethodService den Großteil der Implementierung für die Verwaltung des Status und der Sichtbarkeit des IME sowie für die Kommunikation mit dem aktuellen Eingabefeld.

Die folgenden Klassen sind ebenfalls wichtig:

BaseInputConnection
Definiert den Kommunikationskanal von einer InputMethod zur Anwendung, die ihre Eingabe empfängt. Damit lesen Sie Text um den Cursor herum, führen Text im Textfeld aus und senden Schlüsselereignisse in Rohform an die Anwendung. Anwendungen müssen diese Klasse erweitern, anstatt die Basisschnittstelle InputConnection zu implementieren.
KeyboardView
Eine Erweiterung von View, die eine Tastatur rendert und auf Nutzereingabeereignisse reagiert. Das Tastaturlayout wird durch eine Instanz von Keyboard festgelegt, die Sie in einer XML-Datei definieren können.

Benutzeroberfläche für die Eingabemethode entwerfen

Es gibt zwei visuelle Hauptelemente für einen IME: die Ansicht input und die candidates-Ansicht. Sie müssen nur die Elemente implementieren, die für die von Ihnen entworfene Eingabemethode relevant sind.

Eingabeansicht

Die Eingabeansicht ist die UI, in die der Nutzer Text in Form von Tastaturklicks, Handschrift oder Gesten eingibt. Wenn der IME zum ersten Mal angezeigt wird, ruft das System den onCreateInputView()-Callback auf. Erstellen Sie bei der Implementierung dieser Methode das Layout, das im IME-Fenster angezeigt werden soll, und geben Sie es an das System zurück. Das folgende Snippet zeigt ein Beispiel für die Implementierung der Methode onCreateInputView():

Kotlin

override fun onCreateInputView(): View {
    return layoutInflater.inflate(R.layout.input, null).apply {
        if (this is MyKeyboardView) {
            setOnKeyboardActionListener(this@MyInputMethod)
            keyboard = latinKeyboard
        }
    }
}

Java

@Override
public View onCreateInputView() {
    MyKeyboardView inputView =
        (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null);

    inputView.setOnKeyboardActionListener(this);
    inputView.setKeyboard(latinKeyboard);

    return inputView;
}

In diesem Beispiel ist MyKeyboardView eine Instanz einer benutzerdefinierten Implementierung von KeyboardView, die eine Keyboard rendert.

Kandidatenansicht

Die Kandidatenansicht ist die Benutzeroberfläche, auf der der IME potenzielle Wortkorrekturen oder Vorschläge zur Auswahl durch den Nutzer anzeigt. Im IME-Lebenszyklus ruft das System onCreateCandidatesView() auf, wenn es zur Anzeige der Kandidatenansicht bereit ist. Bei der Implementierung dieser Methode geben Sie ein Layout zurück, in dem Wortvorschläge angezeigt werden, oder geben Sie null zurück, wenn nichts angezeigt werden soll. Eine Null-Antwort ist das Standardverhalten. Sie müssen dies also nicht implementieren, wenn Sie keine Vorschläge machen.

Überlegungen zum UI-Design

In diesem Abschnitt werden einige Überlegungen zum UI-Design für IMEs beschrieben.

Mehrere Bildschirmgrößen verarbeiten

Die Benutzeroberfläche Ihres IME muss für verschiedene Bildschirmgrößen skaliert werden können und sowohl Quer- als auch Hochformat unterstützen. Lassen Sie im Nicht-Vollbild-IME-Modus genügend Platz für die Anwendung, um das Textfeld und den zugehörigen Kontext anzuzeigen, sodass nicht mehr als die Hälfte des Bildschirms vom IME eingenommen wird. Im Vollbildmodus ist das kein Problem.

Verschiedene Eingabetypen verarbeiten

In Android-Textfeldern können Sie einen bestimmten Eingabetyp festlegen, z. B. Freitext, Zahlen, URLs, E-Mail-Adressen und Suchstrings. Wenn Sie einen neuen IME implementieren, ermitteln Sie den Eingabetyp jedes Felds und stellen Sie die entsprechende Schnittstelle bereit. Sie müssen Ihren IME jedoch nicht einrichten, um zu prüfen, ob der Nutzer gültigen Text für den Eingabetyp eingibt. Dies liegt in der Verantwortung der Anwendung, der das Textfeld gehört.

Hier sehen Sie beispielsweise die Schnittstelle, die der Latin-IME für die Texteingabe der Android-Plattform bereitstellt:

Ein Bild, das eine Texteingabe in einem lateinamerikanischen IME zeigt
Abbildung 2. Eingabe für lateinischen IME.

Hier ist die Schnittstelle, die der Latin-IME für die numerische Eingabe der Android-Plattform bietet:

Ein Bild, das eine numerische Eingabe für einen Latin-IME zeigt
Abbildung 3: Numerischer IME (Latin)

Wenn ein Eingabefeld den Fokus erhält und Ihr IME gestartet wird, ruft das System onStartInputView() auf und übergibt ein EditorInfo-Objekt, das Details zum Eingabetyp und andere Attribute des Textfelds enthält. In diesem Objekt enthält das Feld inputType den Eingabetyp des Textfelds.

Das Feld inputType ist ein int, das Bitmuster für verschiedene Einstellungen des Eingabetyps enthält. Um den Eingabetyp des Textfelds zu testen, maskieren Sie ihn so mit der Konstanten TYPE_MASK_CLASS:

Kotlin

inputType and InputType.TYPE_MASK_CLASS

Java

inputType & InputType.TYPE_MASK_CLASS

Das Bitmuster des Eingabetyps kann einen von mehreren Werten haben, darunter:

TYPE_CLASS_NUMBER
Ein Textfeld zur Eingabe von Zahlen. Wie in Abbildung 3 dargestellt, zeigt der lateinische IME für Felder dieses Typs ein Ziffernblock an.
TYPE_CLASS_DATETIME
Ein Textfeld zur Eingabe von Datum und Uhrzeit.
TYPE_CLASS_PHONE
Ein Textfeld zur Eingabe von Telefonnummern.
TYPE_CLASS_TEXT
Ein Textfeld, in das alle unterstützten Zeichen eingegeben werden können.

Diese Konstanten werden in der Referenzdokumentation zu InputType ausführlicher beschrieben.

Das Feld inputType kann andere Bits enthalten, die eine Variante des Textfeldtyps angeben, z. B.:

TYPE_TEXT_VARIATION_PASSWORD
Eine Variante von TYPE_CLASS_TEXT für die Eingabe von Passwörtern. Die Eingabemethode zeigt Dingbats anstelle des tatsächlichen Texts an.
TYPE_TEXT_VARIATION_URI
Eine Variante von TYPE_CLASS_TEXT zur Eingabe von Web-URLs und anderen URIs (Uniform Resource Identifiers).
TYPE_TEXT_FLAG_AUTO_COMPLETE
Eine Variante von TYPE_CLASS_TEXT zur Eingabe von Text, der von der Anwendung automatisch aus einem Wörterbuch, einer Suche oder einer anderen Einrichtung vervollständigt wird.

Maskieren Sie inputType mit der entsprechenden Konstante, wenn Sie diese Varianten testen. Die verfügbaren Maskenkonstanten sind in der Referenzdokumentation zu InputType aufgeführt.

Text an die Anwendung senden

Wenn der Nutzer Text mit Ihrem IME eingibt, können Sie Text an die Anwendung senden. Dazu senden Sie einzelne Schlüsselereignisse oder bearbeiten den Text um den Cursor im Textfeld der Anwendung. Verwenden Sie in beiden Fällen eine Instanz von InputConnection, um den Text zu senden. Rufen Sie InputMethodService.getCurrentInputConnection() auf, um diese Instanz abzurufen.

Text um den Cursor herum bearbeiten

Im Folgenden finden Sie einige nützliche Methoden in BaseInputConnection, wenn Sie vorhandenen Text bearbeiten:

getTextBeforeCursor()
Gibt ein CharSequence-Objekt zurück, das die Anzahl der angeforderten Zeichen vor der aktuellen Cursorposition enthält.
getTextAfterCursor()
Gibt einen CharSequence-Wert zurück, der die Anzahl der angeforderten Zeichen nach der aktuellen Cursorposition enthält.
deleteSurroundingText()
Löscht die angegebene Anzahl von Zeichen vor und nach der aktuellen Cursorposition.
commitText()
Die Nachricht „CharSequence“ wird an das Textfeld gesendet und eine neue Cursorposition festgelegt.

Das folgende Snippet zeigt beispielsweise, wie die vier Zeichen links vom Cursor durch den Text „Hello!“ ersetzt werden:

Kotlin

currentInputConnection.also { ic: InputConnection ->
    ic.deleteSurroundingText(4, 0)
    ic.commitText("Hello", 1)
    ic.commitText("!", 1)
}

Java

InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);

Unterstützung beim Verfassen von Text vor dem Commit unterstützen

Wenn Ihr IME Text vorhersagt oder mehrere Schritte zum Erstellen eines Symbols oder Wortes erfordert, können Sie den Fortschritt im Textfeld anzeigen, bis der Nutzer das Wort festschreibt. Anschließend können Sie die Teilzusammensetzung durch den vollständigen Text ersetzen. Sie können den Text besonders aufwerten, indem Sie ihm bei der Übergabe an setComposingText() ein span-Element hinzufügen.

Das folgende Snippet zeigt, wie der Fortschritt in einem Textfeld angezeigt wird:

Kotlin

currentInputConnection.also { ic: InputConnection ->
    ic.setComposingText("Composi", 1)
    ic.setComposingText("Composin", 1)
    ic.commitText("Composing ", 1)
}

Java

InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);

Hardware-Schlüsselereignisse abfangen

Auch wenn das Eingabemethodenfenster keinen ausdrücklichen Fokus hat, empfängt es zuerst Hardware-Schlüsselereignisse und kann sie verarbeiten oder an die Anwendung weiterleiten. Sie können beispielsweise die Richtungstasten verwenden, um innerhalb Ihrer UI für die Auswahl von Kandidaten während der Erstellung zu navigieren. Sie können auch die Zurück-Taste erfassen, um alle Dialogfelder zu schließen, die aus dem Fenster der Eingabemethode stammen.

Wenn Sie Hardwareschlüssel abfangen möchten, überschreiben Sie onKeyDown() und onKeyUp().

Rufen Sie die Methode super() für Schlüssel auf, die Sie nicht selbst verwalten möchten.

IME-Untertyp erstellen

Mithilfe von Subtypen kann der IME mehrere Eingabemodi und Sprachen anzeigen, die von einem IME unterstützt werden. Ein Untertyp kann Folgendes darstellen:

  • Eine Sprache, z. B. en_US oder fr_FR
  • Einen Eingabemodus, z. B. Sprache, Tastatur oder Handschrift
  • Andere Eingabestile, Formulare oder Eigenschaften, die für den IME spezifisch sind, z. B. 10-Tasten- oder QWERTY-Tastaturlayouts

Als Modus kann ein beliebiger Text festgelegt werden, z. B. „Tastatur“ oder „Spracheingabe“. Für einen Untertyp kann auch eine Kombination daraus verwendet werden.

Untertypinformationen werden für ein IME-Wechsler-Dialogfeld verwendet, das in der Benachrichtigungsleiste und für die IME-Einstellungen verfügbar ist. Anhand der Informationen kann das Framework auch direkt einen bestimmten Untertyp eines IMEs aufrufen. Verwenden Sie beim Erstellen eines IME die Untertypfunktion, da die Nutzer damit verschiedene IME-Sprachen und -Modi identifizieren und zwischen diesen wechseln können.

Definieren Sie Untertypen in einer der XML-Ressourcendateien der Eingabemethode mit dem Element <subtype>. Mit dem folgenden Code-Snippet wird ein IME mit zwei Untertypen definiert: einem Tastaturuntertyp für das Gebietsschema „Englisch (USA)“ und einem weiteren Tastaturuntertyp für die Sprache Französisch für Frankreich:

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon">
    <subtype android:name="@string/display_name_english_keyboard_ime"
            android:icon="@drawable/subtype_icon_english_keyboard_ime"
            android:languageTag="en-US"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="somePrivateOption=true" />
    <subtype android:name="@string/display_name_french_keyboard_ime"
            android:icon="@drawable/subtype_icon_french_keyboard_ime"
            android:languageTag="fr-FR"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" />
    <subtype android:name="@string/display_name_german_keyboard_ime" ... />
</input-method>

Um sicherzustellen, dass Ihre Untertypen in der UI korrekt gekennzeichnet sind, verwenden Sie "%s", um ein Untertyplabel zu erhalten, das dem Sprachlabel des Untertyps entspricht. Dies wird in den nächsten beiden Code-Snippets gezeigt. Das erste Snippet zeigt einen Teil der XML-Datei der Eingabemethode:

<subtype
    android:label="@string/label_subtype_generic"
    android:imeSubtypeLocale="en_US"
    android:icon="@drawable/icon_en_us"
    android:imeSubtypeMode="keyboard" />

Das nächste Snippet ist Teil der strings.xml-Datei des IME. Die Stringressource label_subtype_generic, die von der UI-Definition der Eingabemethode verwendet wird, um das Label des Untertyps festzulegen, ist so definiert:

<string name="label_subtype_generic">%s</string>

Mit dieser Einstellung stimmt der Anzeigename des Untertyps mit der Spracheinstellung überein. In jeder englischen Sprache ist der Anzeigename beispielsweise „English (United States)“.

IME-Untertypen in der Benachrichtigungsleiste auswählen

Das Android-System verwaltet alle von allen IMEs bereitgestellten Untertypen. IME-Untertypen werden als Modi des IME behandelt, zu dem sie gehören. Der Nutzer kann von der Benachrichtigungsleiste oder der App „Einstellungen“ zu einem Menü mit verfügbaren IME-Untertypen wechseln, wie in der folgenden Abbildung dargestellt:

Bild, auf dem das Menü „Sprachen und Eingabe“ zu sehen ist
Abbildung 4: Das Systemmenü Sprachen & Eingabe.

IME-Untertypen in den Systemeinstellungen auswählen

Der Nutzer kann außerdem in den Systemeinstellungen im Einstellungsbereich Sprache und Eingabe steuern, wie Untertypen verwendet werden:

Bild, auf dem das Auswahlmenü für Sprachen zu sehen ist
Abbildung 5: Über das Systemmenü Sprachen

Zwischen IME-Subtypen wechseln

Sie können Nutzern ermöglichen, einfach zwischen IME-Untertypen zu wechseln, indem Sie eine Schaltertaste bereitstellen, z. B. das globeförmige Sprachsymbol auf der Tastatur. Dies verbessert die Nutzungsfreundlichkeit der Tastatur und ist für die Nutzenden praktisch. So aktivieren Sie diesen Wechsel:

  1. Deklarieren Sie supportsSwitchingToNextInputMethod = "true" in den XML-Ressourcendateien der Eingabemethode. Ihre Deklaration muss dem folgenden Code-Snippet ähneln:
    <input-method xmlns:android="http://schemas.android.com/apk/res/android"
            android:settingsActivity="com.example.softkeyboard.Settings"
            android:icon="@drawable/ime_icon"
            android:supportsSwitchingToNextInputMethod="true">
    
  2. Rufen Sie die Methode shouldOfferSwitchingToNextInputMethod() auf.
  3. Wenn die Methode „true“ zurückgibt, wird eine Schalttaste angezeigt.
  4. Wenn der Nutzer auf die Wechseltaste tippt, rufen Sie switchToNextInputMethod() auf und übergeben Sie „false“. Der Wert „false“ weist das System an, alle Untertypen unabhängig davon, zu welchem IME sie gehören, gleich zu behandeln. Wenn Sie „true“ angeben, muss das System die Untertypen im aktuellen IME durchlaufen.

Allgemeine IME-Überlegungen

Weitere Punkte, die Sie bei der Implementierung Ihres IME berücksichtigen sollten:

  • Nutzern die Möglichkeit bieten, Optionen direkt über die IME-Benutzeroberfläche festzulegen
  • Bieten Sie Nutzern die Möglichkeit, direkt über die UI der Eingabemethode zu einem anderen IME zu wechseln, da möglicherweise mehrere IMEs auf dem Gerät installiert sind.
  • Rufen Sie die Benutzeroberfläche des IME schnell auf. Bei Bedarf können Sie große Ressourcen vorab laden oder laden, sodass Nutzer den IME sofort sehen, wenn sie auf ein Textfeld tippen. Speichern Sie Ressourcen und Ansichten für nachfolgende Aufrufe der Eingabemethode.
  • Geben Sie große Arbeitsspeicherzuweisungen sofort nach dem Ausblenden des Eingabemethodenfensters frei, damit die Anwendungen genügend Arbeitsspeicher zum Ausführen haben. Verwenden Sie eine verzögerte Nachricht, um Ressourcen freizugeben, wenn der IME einige Sekunden lang ausgeblendet ist.
  • Achten Sie darauf, dass Nutzer für die mit dem IME verknüpfte Sprache so viele Zeichen wie möglich eingeben können. Nutzer verwenden möglicherweise Satzzeichen in Passwörtern oder Nutzernamen. Daher muss Ihr IME viele verschiedene Zeichen bereitstellen, damit Nutzer ein Passwort eingeben und auf das Gerät zugreifen können.