Eingabekompatibilität auf großen Bildschirmen

Auf Geräten mit großem Bildschirm interagieren Nutzer häufig über eine Tastatur, eine Maus, ein Trackpad, einen Eingabestift oder ein Gamepad mit Apps. So ermöglichen Sie Ihrer App, Eingaben von externen Geräten zu akzeptieren:

  • Testen Sie die grundlegende Tastaturunterstützung, z. B. Strg + Z zum Rückgängigmachen, Strg + C zum Kopieren und Strg + S zum Speichern. Eine Liste der Standard-Tastenkombinationen finden Sie unter Tastaturaktionen verarbeiten.
  • Teste die erweiterte Tastaturunterstützung, z. B. die Tastaturnavigation mit der Tabulatortaste und den Pfeiltasten, die Bestätigung der Texteingabe mit der Eingabetaste und die Wiedergabe und Pause mit der Leertaste in Medien-Apps.
  • Teste grundlegende Mausinteraktionen, einschließlich Rechtsklick für das Kontextmenü, Symboländerungen beim Bewegen des Mauszeigers und Mausrad- oder Trackpad-Scrollereignisse auf benutzerdefinierten Komponenten.
  • App-spezifische Eingabegeräte testen, z. B. Eingabestifte, Gamecontroller und MIDI-Controller für Musik-Apps.
  • Erwäge erweiterte Eingabeunterstützung, mit der sich die App in Desktopumgebungen abheben könnte, z. B. Touchpad als Crossfader für DJ-Apps, Maus-Capture für Spiele und Tastenkombinationen für Nutzer, die hauptsächlich die Tastatur verwenden.

Tastatur

Die Art und Weise, wie deine App auf Tastatureingaben reagiert, trägt zur Nutzerfreundlichkeit auf großen Bildschirmen bei. Es gibt drei Arten von Tastatureingaben: Navigation, Tastendrücke und Tastenkombinationen.

Die Tastaturnavigation wird in Touch-orientierten Apps selten implementiert, aber Nutzer erwarten sie, wenn sie eine App verwenden und ihre Hände auf einer Tastatur haben. Die Tastaturnavigation kann auf Smartphones, Tablets, faltbaren Geräten und Desktop-Geräten für Nutzer mit besonderen Anforderungen an die Barrierefreiheit im Internet unerlässlich sein.

In vielen Apps wird die Navigation mit den Pfeiltasten und der Tabulatortaste automatisch vom Android-Framework übernommen. Einige Composables sind beispielsweise standardmäßig fokussierbar, z. B. ein Button oder ein Composable mit dem Modifikator clickable. Die Tastaturnavigation sollte im Allgemeinen ohne zusätzlichen Code funktionieren. Wenn Sie die Tastaturnavigation für benutzerdefinierte Composeables aktivieren möchten, die standardmäßig nicht fokussierbar sind, fügen Sie den Modifikator focusable hinzu:

var color by remember { mutableStateOf(Green) }
Box(
    Modifier
        .background(color)
        .onFocusChanged { color = if (it.isFocused) Blue else Green }
        .focusable()
) {
    Text("Focusable 1")
}

Weitere Informationen finden Sie unter Composable fokussierbar machen.

Wenn der Fokus aktiviert ist, erstellt das Android-Framework eine Navigationszuordnung für alle fokussierbaren Komponenten basierend auf ihrer Position. Das funktioniert in der Regel wie erwartet und es ist keine weitere Entwicklung erforderlich.

Compose bestimmt jedoch nicht immer das richtige nächste Element für die Tab-Navigation für komplexe Composables wie Tabs und Listen, z. B. wenn eines der Composables ein horizontal scrollbares Element ist, das nicht vollständig sichtbar ist.

Wenn Sie das Fokusverhalten steuern möchten, fügen Sie dem übergeordneten Compose-Element einer Sammlung von Compose-Elementen den Modifikator focusGroup hinzu. Der Fokus wird auf die Gruppe und dann durch die Gruppe bewegt, bevor er zur nächsten fokussierbaren Komponente wechselt, z. B.:

Row {
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col1") }
        Button({}) { Text("Row2 Col1") }
        Button({}) { Text("Row3 Col1") }
    }
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col2") }
        Button({}) { Text("Row2 Col2") }
        Button({}) { Text("Row3 Col2") }
    }
}

Weitere Informationen finden Sie unter Kohärente Navigation mit Fokusgruppen bereitstellen.

Testen Sie den Zugriff auf jedes UI-Element Ihrer App nur mit der Tastatur. Häufig verwendete Elemente sollten ohne Maus oder Eingabe per Berührung zugänglich sein.

Denken Sie daran, dass die Tastaturunterstützung für Nutzer mit besonderen Anforderungen an die Barrierefreiheit im Internet unerlässlich sein kann.

Tastenanschläge

Bei Texteingaben, die über eine virtuelle Bildschirmtastatur (IME) erfolgen, z. B. für TextField , sollten sich Apps auf Geräten mit großen Bildschirmen ohne zusätzlichen Entwicklungsaufwand wie erwartet verhalten. Bei Tastenanschlägen, die vom Framework nicht vorhergesehen werden können, müssen Apps das Verhalten selbst verarbeiten. Das gilt insbesondere für Apps mit benutzerdefinierten Ansichten.

Beispiele hierfür sind Chat-Apps, bei denen Nachrichten mit der Eingabetaste gesendet werden, Medien-Apps, bei denen die Wiedergabe mit der Leertaste gestartet und gestoppt wird, und Spiele, bei denen die Bewegung mit den Tasten W, A, S und D gesteuert wird.

Einzelne Tastenanschläge können Sie mit dem Modifikator onKeyEvent verarbeiten. Dieser akzeptiert einen Lambda-Ausdruck, der aufgerufen wird, wenn die modifizierte Komponente ein Schlüsselereignis empfängt. Mit der Property KeyEvent#type können Sie feststellen, ob das Ereignis ein Tastendruck (KeyDown) oder ein Loslassen der Taste (KeyUp) ist:

Box(
    modifier = Modifier.focusable().onKeyEvent {
        if(
            it.type == KeyEventType.KeyUp &&
            it.key == Key.S
        ) {
            doSomething()
            true
        } else {
            false
        }
    }
)  {
    Text("Press S key")
}

Alternativ kannst du den Callback onKeyUp() überschreiben und das erwartete Verhalten für jeden empfangenen Tastencode hinzufügen:

kotlin override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }

Ein onKeyUp-Ereignis tritt auf, wenn eine Taste losgelassen wird. Durch die Verwendung des Callbacks müssen Apps nicht mehrere onKeyDown-Ereignisse verarbeiten, wenn eine Taste gedrückt gehalten oder langsam losgelassen wird. Spiele und Apps, die den Moment erkennen müssen, in dem eine Taste gedrückt wird, oder ob der Nutzer eine Taste gedrückt hält, können auf das Ereignis onKeyDown warten und wiederholte onKeyDown-Ereignisse selbst verarbeiten.

Weitere Informationen finden Sie unter Tastaturaktionen verarbeiten.

Verknüpfungen

Bei Verwendung einer Hardwaretastatur werden gängige Tastenkombinationen mit den Tasten Strg, Alt, Umschalttaste und Meta erwartet. Wenn eine App keine Verknüpfungen implementiert, kann das für Nutzer frustrierend sein. Fortgeschrittene Nutzer schätzen auch Tastenkombinationen für häufig verwendete App-spezifische Aufgaben. Kurzbefehle erleichtern die Nutzung einer App und heben sie von Apps ohne Kurzbefehle ab.

Zu den gängigen Tastenkombinationen gehören Strg + S (Speichern), Strg + Z (Rückgängig machen) und Strg + Umschalttaste + Z (Wiederholen). Eine Liste der Standard-Tastenkombinationen finden Sie unter Tastaturaktionen verarbeiten.

Ein KeyEvent-Objekt hat die folgenden Attribute, die angeben, ob Modifikatortasten gedrückt werden:

Beispiel:

Box(
    Modifier.onKeyEvent {
        if (it.isAltPressed && it.key == Key.A) {
            println("Alt + A is pressed")
            true
        } else {
            false
        }
    }
    .focusable()
)

Hier finden Sie weitere Informationen:

Eingabestift

Viele Geräte mit großem Display werden mit einem Eingabestift geliefert. Android-Apps verarbeiten Eingabestifte als Touchscreen-Eingabe. Einige Geräte haben möglicherweise auch ein USB- oder Bluetooth-Zeichentablett, z. B. das Wacom Intuos. Android-Apps können Bluetooth-Eingaben empfangen, aber keine USB-Eingaben.

Wenn du auf MotionEvent-Objekte des Eingabestifts zugreifen möchtest, füge einer Zeichenfläche den Modifikator pointerInteropFilter hinzu. Implementieren Sie eine ViewModel-Klasse mit einer Methode, die Bewegungsereignisse verarbeitet. Übergeben Sie die Methode als onTouchEvent-Lambda des pointerInteropFilter-Modifikators:

@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
   Canvas(modifier = modifier
       .clipToBounds()
       .pointerInteropFilter {
           viewModel.processMotionEvent(it)
       }

   ) {
       // Drawing code here.
   }
}

Das Objekt MotionEvent enthält Informationen zum Ereignis:

Historische Punkte

Android bündelt Eingabeereignisse und liefert sie einmal pro Frame. Ein Eingabestift kann Ereignisse mit viel höheren Frequenzen als das Display melden. Wenn du Zeichen-Apps erstellst, solltest du mit den getHistorical APIs nach Ereignissen suchen, die möglicherweise in der jüngeren Vergangenheit aufgetreten sind:

Handballenerkennung

Wenn Nutzer mit einem Eingabestift in deiner App zeichnen, schreiben oder mit ihr interagieren, berühren sie manchmal den Bildschirm mit der Handfläche. Das Touch-Event (auf ACTION_DOWN oder ACTION_POINTER_DOWN gesetzt) kann an deine App gemeldet werden, bevor das System die versehentliche Berührung mit der Handfläche erkennt und ignoriert.

Android bricht Touch-Events, die durch die Handfläche ausgelöst werden, ab, indem es ein MotionEvent sendet. Wenn deine App ACTION_CANCEL empfängt, brich die Geste ab. Wenn Ihre App ACTION_POINTER_UP empfängt, prüfen Sie, ob FLAG_CANCELED festgelegt ist. Wenn ja, brich die Geste ab.

Prüfen Sie nicht nur auf FLAG_CANCELED. Unter Android 13 (API-Level 33) und höher legt das System FLAG_CANCELED für ACTION_CANCEL-Ereignisse fest, aber nicht unter niedrigeren Android-Versionen.

Android 12

Unter Android 12 (API-Level 32) und niedriger ist die Erkennung der Handballenabweisung nur für Touch-Events mit einem einzelnen Zeiger möglich. Wenn eine Berührung mit der Handfläche der einzige Zeiger ist, bricht das System das Ereignis ab, indem es ACTION_CANCEL für das Bewegungserkennungsereignis-Objekt festlegt. Wenn andere Zeiger gedrückt sind, legt das System ACTION_POINTER_UP fest, was für die Erkennung der Handballenabweisung nicht ausreicht.

Android 13

Wenn unter Android 13 (API-Level 33) und höher eine Berührung mit der Handfläche der einzige Zeiger ist, bricht das System das Ereignis ab, indem es ACTION_CANCEL und FLAG_CANCELED für das Bewegungsergebnisobjekt festlegt. Wenn andere Zeiger gedrückt sind, legt das System ACTION_POINTER_UP und FLAG_CANCELED fest.

Wenn deine App ein Bewegungsereignis mit ACTION_POINTER_UP empfängt, prüfe, ob FLAG_CANCELED vorhanden ist, um festzustellen, ob das Ereignis auf eine Handballenerkennung (oder einen anderen Ereignisabbruch) hinweist.

Notizen-Apps

ChromeOS hat einen speziellen Intent, der registrierte Notizen-Apps für Nutzer sichtbar macht. Wenn du eine App als Notizen-App registrieren möchtest, füge deinem App-Manifest Folgendes hinzu:

<intent-filter>
    <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Wenn eine App im System registriert ist, kann der Nutzer sie als Standard-App für Notizen auswählen. Wenn eine neue Notiz angefordert wird, sollte die App eine leere Notiz erstellen, die für die Eingabe mit dem Eingabestift bereit ist. Wenn der Nutzer ein Bild (z. B. einen Screenshot oder ein heruntergeladenes Bild) mit Anmerkungen versehen möchte, wird die App mit ClipData gestartet, das ein oder mehrere Elemente mit content://-URIs enthält. Die App sollte eine Notiz erstellen, die das erste angehängte Bild als Hintergrundbild verwendet, und in einen Modus wechseln, in dem der Nutzer mit einem Eingabestift auf dem Bildschirm zeichnen kann.

Intents für Notizen ohne Eingabestift testen

Wenn du testen möchtest, ob eine App ohne aktiven Eingabestift korrekt auf Intents für Notizen reagiert, kannst du die Optionen für Notizen in ChromeOS mit der folgenden Methode anzeigen lassen:

  1. In den Entwicklermodus wechseln und das Gerät beschreibbar machen
  2. Drücken Sie Strg + Alt + F2, um ein Terminal zu öffnen.
  3. Führen Sie den Befehl sudo vi /etc/chrome_dev.conf aus
  4. Drücken Sie i, um die Datei zu bearbeiten, und fügen Sie --ash-enable-palette in einer neuen Zeile am Ende der Datei hinzu.
  5. Speichern Sie die Datei, indem Sie Esc drücken, dann :, w, q eingeben und die Eingabetaste drücken.
  6. Drücken Sie Strg + Alt + F1, um zur normalen ChromeOS-Benutzeroberfläche zurückzukehren.
  7. Ab- und wieder anmelden

In der Ablage sollte jetzt ein Eingabestift-Menü angezeigt werden:

  • Tippen Sie in der Ablage auf die Eingabestift-Schaltfläche und wählen Sie Neue Notiz aus. Dadurch sollte eine leere Zeichnungsnotiz geöffnet werden.
  • Erstelle einen Screenshot. Wählen Sie in der Ablage Eingabestift-Taste > Screenshot erstellen aus oder laden Sie ein Bild herunter. In der Benachrichtigung sollte die Option Bild mit Anmerkungen versehen angezeigt werden. Dadurch sollte die App mit dem Bild gestartet werden, das annotiert werden kann.

Unterstützung von Maus und Touchpad

Die meisten Apps müssen in der Regel nur drei Ereignisse verarbeiten, die für große Bildschirme relevant sind: Rechtsklick, Hover und Drag-and-drop.

Rechtsklicken

Alle Aktionen, die dazu führen, dass eine App ein Kontextmenü anzeigt, z. B. Berühren und Halten eines Listenelements, sollten auch auf Rechtsklick-Ereignisse reagieren.

Zur Verarbeitung von Rechtsklick-Ereignissen sollten Apps einen View.OnContextClickListener registrieren:

Box(modifier = Modifier.fillMaxSize()) {
    AndroidView(
        modifier = Modifier.fillMaxSize(),
        factory = { context ->
            val rootView = FrameLayout(context)
            val onContextClickListener =
                View.OnContextClickListener { view ->
                    showContextMenu()
                    true
                }
            rootView.setOnContextClickListener(onContextClickListener)
            rootView
        },
    )
}

Weitere Informationen zum Erstellen von Kontextmenüs finden Sie unter Kontextmenü erstellen.

Mauszeiger hierher bewegen

Wenn du Hover-Ereignisse berücksichtigst, kannst du deine App-Layouts optimieren und nutzerfreundlicher gestalten. Dies gilt insbesondere für benutzerdefinierte-Komponenten:

Die beiden häufigsten Beispiele hierfür sind:

  • Nutzern durch Ändern des Mauszeigersymbols anzeigen, ob ein Element interaktiv ist, z. B. anklickbar oder bearbeitbar
  • Visuelles Feedback zu Elementen in einer großen Liste oder einem großen Raster hinzufügen, wenn der Mauszeiger darüber bewegt wird

Drag-and-Drop

Im Mehrfenstermodus erwarten Nutzer, dass sie Elemente per Drag-and-drop zwischen Apps verschieben können. Das gilt sowohl für Desktop-Geräte als auch für Tablets, Smartphones und faltbare Geräte im Splitscreen-Modus.

Überlege, ob Nutzer wahrscheinlich Elemente in deine App ziehen werden. Beispielsweise sollten Bildbearbeitungsprogramme Fotos, Audioplayer Audiodateien und Zeichenprogramme Fotos empfangen können.

Informationen zum Hinzufügen der Drag-and-drop-Unterstützung finden Sie unter Drag-and-drop und im Blogpost Android on ChromeOS – Implementing Drag & Drop.

Besondere Überlegungen für ChromeOS

Erweiterte Unterstützung für Zeiger

Apps, die Maus- und Touchpad-Eingaben auf erweiterte Weise verarbeiten, sollten einen-pointerInput-Modifikator implementieren, um ein PointerEvent zu erhalten:

@Composable
private fun LogPointerEvents(filter: PointerEventType? = null) {
    var log by remember { mutableStateOf("") }
    Column {
        Text(log)
        Box(
            Modifier
                .size(100.dp)
                .background(Color.Red)
                .pointerInput(filter) {
                    awaitPointerEventScope {
                        while (true) {
                            val event = awaitPointerEvent()
                            // handle pointer event
                            if (filter == null || event.type == filter) {
                                log = "${event.type}, ${event.changes.first().position}"
                            }
                        }
                    }
                }
        )
    }
}

Prüfen Sie das PointerEvent-Objekt, um Folgendes zu ermitteln:

Controller

Einige Android-Geräte mit großem Display unterstützen bis zu vier Controller. Verwende die standardmäßigen Android-APIs für Gamecontroller, um Gamecontroller zu verarbeiten (siehe Gamecontroller unterstützen).

Die Tasten von Gamecontrollern werden nach einer gängigen Zuordnung gängigen Werten zugeordnet. Allerdings halten sich nicht alle Hersteller von Gamecontrollern an dieselben Zuordnungskonventionen. Du kannst die Nutzerfreundlichkeit erheblich verbessern, wenn du Nutzern die Möglichkeit gibst, verschiedene gängige Controller-Zuordnungen auszuwählen. Weitere Informationen findest du unter Gamepad-Tastendrücke verarbeiten.

Übersetzungsmodus für Eingabe

In ChromeOS ist standardmäßig ein Eingabeübersetzungsmodus aktiviert. Bei den meisten Android-Apps sorgt dieser Modus dafür, dass sie in einer Desktopumgebung wie erwartet funktionieren. Beispiele hierfür sind das automatische Aktivieren des Scrollens mit zwei Fingern auf dem Touchpad, das Scrollen mit dem Mausrad und das Zuordnen von Rohkoordinaten des Displays zu Fensterkoordinaten. Im Allgemeinen müssen App-Entwickler keines dieser Verhaltensweisen selbst implementieren.

Wenn eine App ein benutzerdefiniertes Eingabeverhalten implementiert, z. B. eine benutzerdefinierte Touchpad-Aktion mit zwei Fingern, oder wenn diese Eingabeübersetzungen nicht die von der App erwarteten Eingabeereignisse liefern, können Sie den Eingabeübersetzungsmodus deaktivieren, indem Sie dem Android-Manifest das folgende Tag hinzufügen:

<uses-feature
    android:name="android.hardware.type.pc"
    android:required="false" />

Zusätzliche Ressourcen