Eingabeereignisse – Übersicht

Funktion „Schreiben“ ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Weitere Informationen

Unter Android gibt es mehrere Möglichkeiten, die Ereignisse bei der Interaktion eines Nutzers mit Ihrer App abzufangen. Wenn Sie Ereignisse auf Ihrer Benutzeroberfläche betrachten, werden die Ereignisse aus dem jeweiligen View-Objekt erfasst, mit dem der Nutzer interagiert. Die View-Klasse bietet die Möglichkeit dazu.

Unter den verschiedenen „View“-Klassen, die Sie zum Erstellen Ihres Layouts verwenden, sind Ihnen möglicherweise mehrere öffentliche Callback-Methoden aufgefallen, die für UI-Ereignisse nützlich aussehen. Diese Methoden werden vom Android-Framework aufgerufen, wenn die entsprechende Aktion an diesem Objekt ausgeführt wird. Wenn beispielsweise eine Ansicht (z. B. eine Schaltfläche) angeklickt wird, wird die Methode onTouchEvent() für dieses Objekt aufgerufen. Um dies jedoch abzufangen, müssen Sie die Klasse erweitern und die Methode überschreiben. Es wäre jedoch nicht praktikabel, jedes View-Objekt zu erweitern, um ein solches Ereignis zu verarbeiten. Aus diesem Grund enthält die Ansichtsklasse auch eine Sammlung verschachtelter Schnittstellen mit Callbacks, die sich viel einfacher definieren lassen. Diese Benutzeroberflächen, auch Event-Listener genannt, sind Ihr Ticket, um die Nutzerinteraktion mit Ihrer UI zu erfassen.

Obwohl Sie normalerweise die Ereignis-Listener verwenden, um auf Nutzerinteraktionen zu warten, kann es sinnvoll sein, eine View-Klasse zu erweitern, um eine benutzerdefinierte Komponente zu erstellen. Vielleicht möchten Sie die Button-Klasse erweitern, um etwas raffinierteres zu gestalten. In diesem Fall können Sie das Standardereignisverhalten für Ihre Klasse mithilfe der Klasse Event-Handler definieren.

Ereignis-Listener

Ein Event-Listener ist eine Schnittstelle in der Klasse View, die eine einzelne Callback-Methode enthält. Diese Methoden werden vom Android-Framework aufgerufen, wenn die Ansicht, für die der Listener registriert wurde, durch Nutzerinteraktion mit dem Element in der UI ausgelöst wird.

In den Event-Listener-Oberflächen sind die folgenden Callback-Methoden enthalten:

onClick()
Ab View.OnClickListener. Dies wird aufgerufen, wenn der Nutzer entweder das Element berührt (im Touch-Modus) oder mit den Navigationstasten oder dem Trackball den Fokus auf das Element legt und die entsprechende Eingabetaste drückt oder den Trackball nach unten drückt.
onLongClick()
Ab View.OnLongClickListener. Dies wird aufgerufen, wenn der Nutzer das Element entweder berührt und hält (im Touch-Modus) oder mit den Navigationstasten oder dem Trackball den Fokus auf das Element legt und die entsprechende Eingabetaste drückt und hält oder den Trackball eine Sekunde lang drückt.
onFocusChange()
Ab View.OnFocusChangeListener. Dies wird aufgerufen, wenn der Nutzer mithilfe der Navigationstasten oder des Trackballs zum Artikel navigiert oder ihn verlässt.
onKey()
Ab View.OnKeyListener. Sie wird aufgerufen, wenn der Nutzer den Fokus auf den Artikel legt und eine Hardwaretaste am Gerät drückt oder wieder loslässt.
onTouch()
Ab View.OnTouchListener. Dies wird aufgerufen, wenn der Nutzer eine als Touch-Ereignis eingestufte Aktion ausführt, z. B. das Drücken, eine Veröffentlichung oder eine Bewegungsgeste auf dem Bildschirm (innerhalb des Artikelbereichs).
onCreateContextMenu()
Ab View.OnCreateContextMenuListener. Sie wird beim Erstellen eines Kontextmenüs als Ergebnis eines anhaltenden „langen Klicks“ aufgerufen. Weitere Informationen finden Sie in der Diskussion zu Kontextmenüs im Entwicklerleitfaden für Menüs.

Diese Methoden sind die einzigen Bewohner ihrer jeweiligen Oberfläche. Um eine dieser Methoden zu definieren und deine Ereignisse zu verarbeiten, implementiere die verschachtelte Schnittstelle in deiner Aktivität oder definiere sie als anonyme Klasse. Übergeben Sie dann eine Instanz Ihrer Implementierung an die entsprechende View.set...Listener()-Methode. Rufen Sie z.B. setOnClickListener() auf und übergeben Sie die Implementierung von OnClickListener.

Das folgende Beispiel zeigt, wie ein On-Click-Listener für eine Schaltfläche registriert wird.

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

Möglicherweise finden Sie es auch einfacher, OnClickListener als Teil Ihrer Aktivität zu implementieren. Dadurch werden zusätzliche Klassenlasten und Objektzuweisungen vermieden. Beispiel:

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Der onClick()-Callback im obigen Beispiel hat keinen Rückgabewert. Einige andere Ereignis-Listener-Methoden müssen jedoch einen booleschen Wert zurückgeben. Der Grund hängt vom Ereignis ab. Der Grund für die wenigen, die dies tun, hat folgenden Grund:

  • onLongClick(): Gibt einen booleschen Wert zurück, der angibt, ob das Ereignis verarbeitet wurde und nicht weiter übertragen werden soll. Geben Sie also true zurück, um anzugeben, dass Sie das Ereignis verarbeitet haben und es hier beendet werden sollte. Geben Sie false zurück, wenn Sie es noch nicht verarbeitet haben, und/oder das Ereignis sollte mit einem anderen On-Click-Listener fortfahren.
  • onKey(): Gibt einen booleschen Wert zurück, der angibt, ob das Ereignis verarbeitet wurde und nicht weiter übertragen werden soll. Geben Sie also true zurück, um anzugeben, dass Sie das Ereignis verarbeitet haben und es hier beendet werden sollte. Geben Sie false zurück, wenn Sie es noch nicht verarbeitet haben, und/oder das Ereignis sollte mit allen anderen On-Key-Listenern fortfahren.
  • onTouch(): Gibt einen booleschen Wert zurück, der angibt, ob der Listener dieses Ereignis aufnimmt. Wichtig ist, dass dieses Ereignis mehrere Aktionen haben kann, die aufeinander folgen. Wenn Sie also false zurückgeben, wenn das Down-Action-Ereignis empfangen wird, geben Sie an, dass Sie das Ereignis nicht genutzt haben und auch kein Interesse an nachfolgenden Aktionen aus diesem Ereignis haben. Du wirst daher zu keinen anderen Aktionen innerhalb des Ereignisses aufgerufen, z. B. zu einer Fingergeste oder dem schließlich stattfindenden Ereignis „Aufwärtsaktion“.

Denken Sie daran, dass Hardware-Schlüsselereignisse immer in der aktuell aktiven Ansicht wiedergegeben werden. Sie werden vom oberen Rand der Ansichtshierarchie nach unten geleitet, bis sie das entsprechende Ziel erreichen. Wenn Ihre Ansicht (oder ein untergeordnetes Element Ihrer Datenansicht) aktuell im Fokus ist, können Sie das Ereignis mit der dispatchKeyEvent()-Methode sehen. Anstatt wichtige Ereignisse über Ihre Datenansicht zu erfassen, können Sie auch alle Ereignisse in Ihren Aktivitäten mit onKeyDown() und onKeyUp() empfangen.

Denken Sie bei der Texteingabe für Ihre Anwendung auch daran, dass viele Geräte nur Software-Eingabemethoden haben. Solche Methoden müssen nicht schlüsselbasiert sein. Einige können Spracheingabe, Handschrift usw. verwenden. Selbst wenn eine Eingabemethode eine tastaturähnliche Schnittstelle aufweist, wird die Ereignisfamilie onKeyDown() in der Regel nicht ausgelöst. Sie sollten niemals eine UI erstellen, für die bestimmte Tastenanschläge gesteuert werden müssen, es sei denn, Sie möchten Ihre Anwendung auf Geräte mit einer Hardwaretastatur beschränken. Verlassen Sie sich insbesondere nicht auf diese Methoden, um Eingaben zu validieren, wenn der Nutzer die Eingabetaste drückt. Verwenden Sie stattdessen Aktionen wie IME_ACTION_DONE, um der Eingabemethode zu signalisieren, wie Ihre Anwendung reagieren soll. Dadurch kann die Benutzeroberfläche sinnvoll geändert werden. Vermeiden Sie Vermutungen darüber, wie eine Softwareeingabemethode funktionieren sollte, und vertrauen Sie einfach darauf, dass Ihrer Anwendung bereits formatierter Text bereitgestellt wird.

Hinweis:Android ruft zuerst Event-Handler und dann die entsprechenden Standard-Handler aus der Klassendefinition auf. Wenn von diesen Ereignis-Listenern true zurückgegeben wird, wird die Weitergabe des Ereignisses an andere Ereignis-Listener gestoppt. Außerdem wird der Callback an den Standard-Event-Handler in der Ansicht blockiert. Achten Sie also darauf, dass das Ereignis beendet werden soll, wenn Sie true zurückgeben.

Event-Handler

Wenn Sie eine benutzerdefinierte Komponente aus der Ansicht erstellen, können Sie mehrere Callback-Methoden definieren, die als Standard-Event-Handler verwendet werden. Im Dokument zu Komponenten der benutzerdefinierten Ansicht finden Sie einige häufige Callbacks, die für die Ereignisverarbeitung verwendet werden, darunter:

Es gibt einige andere Methoden, die Sie kennen sollten. Diese sind nicht Teil der Ansichtsklasse, können sich aber direkt auf die Verarbeitung von Ereignissen auswirken. Wenn Sie komplexere Ereignisse in einem Layout verwalten möchten, könnten diese Methoden also sinnvoll sein:

Touchmodus

Wenn ein Nutzer mit Richtungstasten oder einem Trackball in einer Benutzeroberfläche navigieren, ist es erforderlich, auf praktische Elemente (wie Schaltflächen) zu konzentrieren, damit der Nutzer sehen kann, welche Eingabe akzeptiert wird. Wenn das Gerät jedoch Touchfunktionen hat und der Nutzer beginnt, mit der Oberfläche zu interagieren, indem er darauf tippt, ist es nicht mehr erforderlich, Elemente hervorzuheben oder den Fokus auf eine bestimmte Ansicht zu legen. Daher gibt es einen Interaktionsmodus namens „Touch-Modus“.

Sobald der Nutzer den Bildschirm berührt, wechselt das Gerät in den Touchmodus. Ab diesem Zeitpunkt können nur noch Ansichten in Ansichten, für die isFocusableInTouchMode() wahr ist, fokussiert werden, z. B. Textbearbeitungs-Widgets. Andere Ansichten, die angetippt werden können (z. B. Schaltflächen), werden beim Berühren nicht hervorgehoben. Sie lösen einfach die jeweiligen Listener aus, die bei einem Klick aktiviert werden.

Jedes Mal, wenn ein Nutzer eine Richtungstaste drückt oder mit einem Trackball scrollt, beendet das Gerät den Touchmodus und sucht eine Ansicht, die fokussiert werden soll. Jetzt kann der Nutzer die Interaktion mit der Benutzeroberfläche fortsetzen, ohne den Bildschirm zu berühren.

Der Status des Touchmodus wird über das gesamte System hinweg beibehalten (alle Fenster und Aktivitäten). Um den aktuellen Status abzufragen, kannst du isInTouchMode() aufrufen. Dadurch wird angezeigt, ob sich das Gerät derzeit im Touchmodus befindet.

Fokus bedienen

Das Framework verarbeitet Routinebewegungen des Fokus als Reaktion auf Nutzereingaben. Dazu gehört auch, den Fokus zu ändern, wenn Ansichten entfernt oder ausgeblendet werden oder wenn neue Ansichten verfügbar werden. Ansichten deuten darauf hin, dass sie bereit sind, den Fokus mithilfe der isFocusable()-Methode zu fokussieren. Rufen Sie setFocusable() auf, um festzulegen, ob eine Ansicht fokussiert werden kann. Im Touchmodus können Sie abfragen, ob eine Ansicht den Fokus mit isFocusableInTouchMode() zulässt. Sie können dies mit setFocusableInTouchMode() ändern.

Auf Geräten mit Android 9 (API-Level 28) oder höher wird bei Aktivitäten kein Anfangsfokus zugewiesen. Stattdessen müssen Sie den anfänglichen Fokus gegebenenfalls explizit anfordern.

Die Fokusbewegung basiert auf einem Algorithmus, der den nächsten Nachbarn in einer bestimmten Richtung findet. In seltenen Fällen kann es vorkommen, dass der Standardalgorithmus nicht dem gewünschten Verhalten des Entwicklers entspricht. In diesen Fällen können Sie explizite Überschreibungen mit den folgenden XML-Attributen in der Layoutdatei angeben: nextFocusDown, nextFocusLeft, nextFocusRight und nextFocusUp. Fügen Sie eines dieser Attribute der Ansicht hinzu, von der aus der Fokus liegt. Definieren Sie den Attributwert als ID der Ansicht zu, auf die der Fokus gesetzt werden soll. Beispiel:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

Normalerweise würde es bei diesem vertikalen Layout nirgendwo hingehen, wenn man von der ersten Schaltfläche nach oben navigiert, und von der zweiten Schaltfläche auch nicht nach unten. Nachdem die obere Schaltfläche die untere Schaltfläche als nextFocusUp definiert hat (und umgekehrt), wechselt der Navigationsfokus von oben nach unten und von unten nach oben.

Wenn Sie eine Ansicht in Ihrer UI als fokussierbar deklarieren möchten, wenn dies normalerweise nicht der Fall ist, fügen Sie der Ansicht in Ihrer Layoutdeklaration das XML-Attribut android:focusable hinzu. Legen Sie den Wert true fest. Sie können eine Ansicht auch im Touchmodus mit android:focusableInTouchMode als fokussierbar deklarieren.

Rufen Sie requestFocus() auf, um festzulegen, dass eine bestimmte Ansicht fokussiert werden soll.

Wenn Sie auf Fokusereignisse warten möchten, also benachrichtigt werden, wenn eine Ansicht den Fokus erhält oder verliert, verwenden Sie onFocusChange(), wie im Abschnitt Ereignis-Listener beschrieben.