Eingabeereignisse – Übersicht

Compose ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Informationen zur Verwendung von Touch- und Eingabefunktionen in Compose

Unter Android gibt es mehrere Möglichkeiten, die Ereignisse aus der Interaktion eines Nutzers mit Ihrer Anwendung abzufangen. Wenn Sie Ereignisse in Ihrer Benutzeroberfläche berücksichtigen, sollten Sie die Ereignisse des jeweiligen View-Objekts erfassen, mit dem der Nutzer interagiert. Die View-Klasse bietet die Möglichkeit dazu.

In den verschiedenen View-Klassen, die Sie zum Erstellen Ihres Layouts verwenden, finden Sie möglicherweise mehrere öffentliche Callback-Methoden, die für UI-Ereignisse nützlich erscheinen. Diese Methoden werden vom Android-Framework aufgerufen, wenn die entsprechende Aktion für dieses Objekt ausgeführt wird. Wenn beispielsweise eine View (z. B. eine Schaltfläche) berührt wird, wird die Methode onTouchEvent() für dieses Objekt aufgerufen. Wenn Sie dies abfangen möchten, müssen Sie die Klasse jedoch 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 View-Klasse auch eine Sammlung verschachtelter Schnittstellen mit Callbacks, die Sie viel einfacher definieren können. Diese Schnittstellen, auch Event-Listener genannt, ermöglichen es Ihnen, die Nutzerinteraktion mit Ihrer Benutzeroberfläche zu erfassen.

In der Regel verwenden Sie die Event-Listener, um auf Nutzerinteraktionen zu reagieren. Es kann jedoch vorkommen, dass Sie eine View-Klasse erweitern möchten, um eine benutzerdefinierte Komponente zu erstellen. Vielleicht möchten Sie die Button-Klasse erweitern, um etwas Besonderes zu erstellen. In diesem Fall können Sie das Standardverhalten von Ereignissen für Ihre Klasse mithilfe der Event-Handler der Klasse definieren.

Event-Listener

Ein Event-Listener ist eine Schnittstelle in der View-Klasse, 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 eine Nutzerinteraktion mit dem Element auf der Benutzeroberfläche ausgelöst wird.

Die Event-Listener-Schnittstellen enthalten die folgenden Callback-Methoden:

onClick()
Ab View.OnClickListener. Diese Methode wird aufgerufen, wenn der Nutzer das Element entweder berührt (im Touch-Modus) oder das Element mit den Navigationstasten oder dem Trackball fokussiert und die entsprechende Eingabetaste drückt oder den Trackball nach unten drückt.
onLongClick()
Ab View.OnLongClickListener. Diese Methode wird aufgerufen, wenn der Nutzer das Element entweder berührt und gedrückt hält (im Touch-Modus) oder das Element mit den Navigationstasten oder dem Trackball fokussiert und die entsprechende Eingabetaste oder den Trackball eine Sekunde lang gedrückt hält.
onFocusChange()
Ab View.OnFocusChangeListener. Diese Methode wird aufgerufen, wenn der Nutzer mit den Navigationstasten oder dem Trackball zum Element navigiert oder es verlässt.
onKey()
Ab View.OnKeyListener. Diese Methode wird aufgerufen, wenn der Nutzer den Fokus auf das Element legt und eine Hardwaretaste auf dem Gerät drückt oder loslässt.
onTouch()
Ab View.OnTouchListener. Diese Methode wird aufgerufen, wenn der Nutzer eine Aktion ausführt, die als Touch-Ereignis gilt, z. B. ein Drücken, ein Loslassen oder eine beliebige Bewegungsgeste auf dem Bildschirm (innerhalb der Grenzen des Elements).
onCreateContextMenu()
Ab View.OnCreateContextMenuListener. Diese Methode wird aufgerufen, wenn ein Kontextmenü erstellt wird (als Ergebnis eines längeren Klicks). Weitere Informationen zu Kontextmenüs finden Sie im Entwicklerleitfaden unter Menüs.

Diese Methoden sind die einzigen Elemente ihrer jeweiligen Schnittstelle. Wenn Sie eine dieser Methoden definieren und Ihre Ereignisse verarbeiten möchten, implementieren Sie die verschachtelte Schnittstelle in Ihrer Aktivität oder definieren Sie sie als anonyme Klasse. Übergeben Sie dann eine Instanz Ihrer Implementierung an die entsprechende View.set...Listener()-Methode. Rufen Sie beispielsweise setOnClickListener() auf und übergeben Sie Ihre Implementierung von OnClickListener.

Im folgenden Beispiel wird gezeigt, 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);
    ...
}

Es kann auch praktischer sein, OnClickListener als Teil Ihrer Aktivität zu implementieren. So werden das zusätzliche Laden von Klassen und die Zuweisung von Objekten 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
    }
    ...
}

Beachten Sie, dass der onClick()-Callback im obigen Beispiel keinen Rückgabewert hat. Einige andere Event-Listener-Methoden müssen jedoch einen booleschen Wert zurückgeben. Der Grund hängt vom Ereignis ab. Das kann folgende Gründe haben:

  • onLongClick(): Gibt einen booleschen Wert zurück, der angibt, ob das Ereignis verarbeitet wurde und nicht weitergeleitet werden soll. Das heißt, Sie geben true zurück, um anzugeben, dass Sie das Ereignis verarbeitet haben und es hier beendet werden soll. Geben Sie false zurück, wenn Sie es nicht verarbeitet haben und/oder das Ereignis an andere On-Click-Listener weitergeleitet werden soll.
  • onKey(): Gibt einen booleschen Wert zurück, der angibt, ob das Ereignis verarbeitet wurde und nicht weitergeleitet werden soll. Das heißt, Sie geben true zurück, um anzugeben, dass Sie das Ereignis verarbeitet haben und es hier beendet werden soll. Geben Sie false zurück, wenn Sie es nicht verarbeitet haben und/oder das Ereignis an andere On-Key-Listener weitergeleitet werden soll.
  • onTouch(): Gibt einen booleschen Wert zurück, der angibt, ob der Listener dieses Ereignis verarbeitet. Wichtig ist, dass dieses Ereignis mehrere Aktionen haben kann, die aufeinander folgen. Wenn Sie also false zurückgeben, wenn das Ereignis für die Down-Aktion empfangen wird, geben Sie an, dass Sie das Ereignis nicht verarbeitet haben und auch nicht an nachfolgenden Aktionen aus diesem Ereignis interessiert sind. Sie werden daher nicht zu anderen Aktionen innerhalb des Ereignisses aufgefordert, z. B. zu einer Fingerbewegung oder dem Ereignis „up“ (nach oben).

Hardware-Schlüsselereignisse werden immer an die View übergeben, die gerade im Fokus steht. Sie werden von oben nach unten in der Ansichtshierarchie gesendet, bis sie das entsprechende Ziel erreichen. Wenn Ihre Ansicht (oder eine untergeordnete Ansicht) derzeit den Fokus hat, können Sie sehen, wie das Ereignis durch die Methode dispatchKeyEvent() geleitet wird. Alternativ zum Erfassen von Schlüsselereignissen über Ihre Ansicht können Sie auch alle Ereignisse in Ihrer Aktivität mit onKeyDown() und onKeyUp() empfangen.

Denken Sie auch daran, dass viele Geräte nur Software-Eingabemethoden haben, wenn Sie über die Texteingabe für Ihre Anwendung nachdenken. Für solche Methoden sind keine Schlüssel erforderlich. Einige verwenden möglicherweise Spracheingabe, Handschrift usw. Auch wenn eine Eingabemethode eine tastaturähnliche Oberfläche bietet, werden die Ereignisse der onKeyDown()-Familie in der Regel nicht ausgelöst. Sie sollten niemals eine Benutzeroberfläche entwickeln, die bestimmte Tastendrücke erfordert, 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 mitzuteilen, wie Ihre Anwendung reagieren soll, damit sie ihre Benutzeroberfläche sinnvoll ändern kann. Vermeiden Sie Annahmen darüber, wie eine Software-Eingabemethode funktionieren sollte, und vertrauen Sie darauf, dass sie bereits formatierten Text für Ihre Anwendung bereitstellt.

Hinweis:Unter Android werden zuerst Ereignis-Handler und dann die entsprechenden Standard-Handler aus der Klassendefinition aufgerufen. Wenn Sie also true von diesen Event-Listenern zurückgeben, wird die Weiterleitung des Ereignisses an andere Event-Listener beendet und der Callback an den Standard-Event-Handler in der Ansicht wird blockiert. Sie sollten sich also sicher sein, dass Sie das Ereignis beenden möchten, wenn Sie true zurückgeben.

Event-Handler

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

Es gibt einige andere Methoden, die nicht Teil der View-Klasse sind, aber sich direkt auf die Art und Weise auswirken können, wie Sie Ereignisse verarbeiten. Wenn Sie also komplexere Ereignisse in einem Layout verwalten, sollten Sie diese anderen Methoden in Betracht ziehen:

Touch-Modus

Wenn ein Nutzer eine Benutzeroberfläche mit Richtungstasten oder einem Trackball bedient, müssen interaktive Elemente (z. B. Schaltflächen) fokussiert werden, damit der Nutzer sehen kann, welche Elemente Eingaben akzeptieren. Wenn das Gerät jedoch über Touch-Funktionen verfügt und der Nutzer mit der Benutzeroberfläche interagiert, indem er sie berührt, ist es nicht mehr erforderlich, Elemente hervorzuheben oder den Fokus auf eine bestimmte Ansicht zu legen. Daher gibt es einen Modus für die Interaktion namens „Touch-Modus“.

Wenn der Nutzer ein Gerät mit Touchscreen berührt, wechselt das Gerät in den Touch-Modus. Ab diesem Punkt sind nur noch Ansichten fokussierbar, für die isFocusableInTouchMode() zutrifft, z. B. Widgets zur Textbearbeitung. Andere Ansichten, die berührt werden können, z. B. Schaltflächen, werden bei Berührung nicht fokussiert. Stattdessen werden bei Berührung einfach die On-Click-Listener ausgelöst.

Jedes Mal, wenn ein Nutzer eine Richtungstaste drückt oder mit einem Trackball scrollt, wird der Touch-Modus beendet und eine Ansicht ausgewählt, die den Fokus erhält. Der Nutzer kann jetzt wieder mit der Benutzeroberfläche interagieren, ohne den Bildschirm zu berühren.

Der Touch-Modus wird im gesamten System (alle Fenster und Aktivitäten) beibehalten. Wenn Sie den aktuellen Status abfragen möchten, können Sie isInTouchMode() aufrufen, um zu prüfen, ob sich das Gerät derzeit im Touch-Modus befindet.

Fokus verarbeiten

Das Framework übernimmt die routinemäßige Fokusbewegung als Reaktion auf Nutzereingaben. Dazu gehört auch, den Fokus zu ändern, wenn Ansichten entfernt oder ausgeblendet werden oder neue Ansichten verfügbar werden. Views geben über die Methode isFocusable() an, dass sie bereit sind, den Fokus zu übernehmen. Wenn Sie ändern möchten, ob eine Ansicht den Fokus erhalten kann, rufen Sie setFocusable() auf. Im Touch-Modus können Sie mit isFocusableInTouchMode() abfragen, ob ein View den Fokus zulässt. Sie können dies mit setFocusableInTouchMode() ändern.

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

Die Fokusbewegung basiert auf einem Algorithmus, der den nächsten Nachbarn in einer bestimmten Richtung findet. In seltenen Fällen entspricht der Standardalgorithmus möglicherweise nicht dem vom Entwickler beabsichtigten Verhalten. 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 der Ansicht, aus der der Fokus entfernt wird, eines dieser Attribute hinzu. Definieren Sie den Wert des Attributs als die ID der Ansicht, auf die der Fokus gelegt 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 die Navigation nach oben von der ersten Schaltfläche in diesem vertikalen Layout nirgendwohin führen, ebenso wenig wie die Navigation nach unten von der zweiten Schaltfläche. Nachdem für die obere Schaltfläche die untere als nextFocusUp definiert wurde (und umgekehrt), wird der Navigationsfokus von oben nach unten und von unten nach oben durchlaufen.

Wenn Sie eine View in Ihrer Benutzeroberfläche als fokussierbar deklarieren möchten, obwohl sie es normalerweise nicht ist, fügen Sie das XML-Attribut android:focusable in der Layoutdeklaration zur View hinzu. Legen Sie den Wert true fest. Sie können eine Ansicht auch im Touch-Modus mit android:focusableInTouchMode als fokussierbar deklarieren.

Wenn Sie möchten, dass eine bestimmte Ansicht den Fokus erhält, rufen Sie requestFocus() auf.

Wenn Sie auf Fokusereignisse warten möchten (Benachrichtigung, wenn ein View den Fokus erhält oder verliert), verwenden Sie onFocusChange(), wie im Abschnitt Event-Listener beschrieben.