Auf Geräten mit großen Bildschirmen interagieren Nutzer häufig mit Apps über eine Tastatur, Maus, ein Touchpad, einen Stift oder ein Gamepad. So ermöglichen Sie Ihrer App, Eingaben von externen Geräten zu akzeptieren:
- Grundlegende Tastaturunterstützung testen, z. B. Strg+Z für „Rückgängig“, Strg+C für „Kopieren“ und Strg+S für „Speichern“. Eine Liste der Standardtastenkombinationen finden Sie unter Tastaturaktionen verarbeiten.
- Erweiterte Tastaturunterstützung testen, z. B. die Navigation mit der Tabulatortaste und den Pfeiltasten, die Bestätigung der Texteingabe mit der Eingabetaste sowie das Abspielen und Pausieren in Media-Apps mit der Leertaste.
- Grundlegende Mausinteraktionen testen, einschließlich Rechtsklick für das Kontextmenü, Symboländerungen beim Hovern und Mausrad- oder Touchpad-Scroll-Ereignisse bei benutzerdefinierten Komponenten.
- App-spezifische Eingabegeräte testen, z. B. Stifte, Gamecontroller und MIDI-Controller für Musik-Apps.
- Unterstützung für erweiterte Eingaben kann die App in Desktopumgebungen hervorheben. Beispiele: Touchpad als Crossfader für DJ-Apps, Mauszeigerfang für Spiele und Tastenkombinationen für Nutzer, die hauptsächlich die Tastatur verwenden.
Tastatur
Die Art und Weise, wie Ihre App auf die Tastatureingabe reagiert, trägt zur Nutzerfreundlichkeit auf großen Bildschirmen bei. Es gibt drei Arten von Tastatureingaben: Navigation, Tastendrücke und Tastenkombinationen.
Navigation
Die Tastaturnavigation wird in Apps, die für die Touchbedienung optimiert sind, selten implementiert. Nutzer erwarten sie jedoch, wenn sie eine App verwenden und ihre Hände auf der Tastatur haben. Die Tastaturnavigation kann auf Smartphones, Tablets, Foldables und Desktopgeräten für Nutzer mit Beeinträchtigungen unerlässlich sein.
Bei vielen Apps werden 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 Modifier clickable. Die Tastaturnavigation sollte in der Regel ohne zusätzlichen Code funktionieren. Wenn Sie die Tastaturnavigation für benutzerdefinierte Composables aktivieren möchten, die standardmäßig nicht fokussierbar sind, fügen Sie den Modifier 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 Fokusierbares Composable erstellen.
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 sind keine weiteren Entwicklungen erforderlich.
Compose bestimmt jedoch nicht immer das richtige nächste Element für die Tab-Navigation bei komplexen 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 den Modifier focusGroup der übergeordneten zusammensetzbaren Funktion einer Sammlung von zusammensetzbaren Funktionen hinzu. Der Fokus wird auf die Gruppe und dann durch die Gruppe verschoben, bevor er auf das nächste fokussierbare Element verschoben wird, 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 Fokusgruppen für eine konsistente Navigation.
Testen Sie den Zugriff auf jedes UI-Element Ihrer App ausschließlich über die Tastatur. Häufig verwendete Elemente sollten ohne Maus- oder Toucheingabe zugänglich sein.
Denken Sie daran, dass die Tastaturunterstützung für Nutzer mit Beeinträchtigungen unerlässlich sein kann.
Tastenanschläge
Für die Texteingabe, die von einer virtuellen Bildschirmtastatur (IME) verarbeitet wird, z. B. für
ein TextField
sollten sich Apps auf Geräten mit großem Display wie erwartet verhalten, ohne dass zusätzliche Entwicklungsarbeit erforderlich ist. Bei Tasteneingaben, 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 sind Chat-Apps, in denen Nachrichten mit der Eingabetaste gesendet werden, Medien-Apps, in denen die Wiedergabe mit der Leertaste gestartet und beendet wird, und Spiele, in denen die Bewegung mit den Tasten w, a, s und d gesteuert wird.
Sie können einzelne Tastendrücke mit dem Modifikator onKeyEvent verarbeiten. Dieser akzeptiert ein Lambda, das aufgerufen wird, wenn die geänderte Komponente ein Tastaturereignis empfängt.
Mit dem Attribut KeyEvent#type können Sie ermitteln, 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 können Sie den onKeyUp()-Callback ü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 oder langsam losgelassen wird. Spiele und Apps, die erkennen müssen, wann eine Taste gedrückt wird oder ob der Nutzer eine Taste gedrückt hält, können auf das onKeyDown-Ereignis warten und wiederholte onKeyDown-Ereignisse selbst verarbeiten.
Weitere Informationen finden Sie unter Tastaturaktionen verarbeiten.
Verknüpfungen
Bei Verwendung einer Hardwaretastatur werden gängige Tastenkombinationen erwartet, die die Tasten Strg, Alt, Umschalt und Meta enthalten. Wenn eine App keine Verknüpfungen implementiert, kann das für Nutzer frustrierend sein. Auch fortgeschrittene Nutzer schätzen Tastenkombinationen für häufig verwendete app-spezifische Aufgaben. Kurzbefehle erleichtern die Verwendung 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) und Strg + Umschalt + Z (Wiederholen). Eine Liste der Standardschaltflächen finden Sie unter Tastaturaktionen verarbeiten.
Ein KeyEvent-Objekt hat die folgenden Attribute, die angeben, ob die Umschalttasten 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 behandeln Stifteingaben als Touchscreen-Eingaben. Einige Geräte haben möglicherweise auch ein USB- oder Bluetooth-Zeichentablet, z. B. das Wacom Intuos. Android-Apps können Bluetooth-Eingaben, aber keine USB-Eingaben empfangen.
Wenn Sie auf MotionEvent-Objekte für den Stylus zugreifen möchten, fügen Sie einer Zeichenfläche den Modifier pointerInteropFilter hinzu. Implementieren Sie eine ViewModel-Klasse mit einer Methode, die Bewegungsereignisse verarbeitet, und übergeben Sie die Methode als onTouchEvent-Lambda des pointerInteropFilter-Modifiers:
@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
Canvas(modifier = modifier
.clipToBounds()
.pointerInteropFilter {
viewModel.processMotionEvent(it)
}
) {
// Drawing code here.
}
}
Das MotionEvent-Objekt enthält Informationen zum Ereignis:
MotionEvent#getToolType()gibtTOOL_TYPE_FINGER,TOOL_TYPE_STYLUSoderTOOL_TYPE_ERASERzurück, je nachdem, welches Tool das Display berührt hat.MotionEvent#getPressure()gibt den physischen Druck an, der auf den Eingabestift ausgeübt wird (falls unterstützt).MotionEvent#getAxisValue()mitMotionEvent.AXIS_TILTundMotionEvent.AXIS_ORIENTATIONgeben die physische Neigung und Ausrichtung des Stifts an (falls unterstützt).
Historische Punkte
Android fasst Eingabeereignisse zusammen und stellt sie einmal pro Frame bereit. Ein Stylus kann Ereignisse mit einer viel höheren Frequenz als das Display melden. Wenn Sie Zeichen-Apps erstellen, sollten Sie mit den getHistorical APIs nach Ereignissen suchen, die möglicherweise in der jüngsten Vergangenheit liegen:
MotionEvent#getHistoricalX()MotionEvent#getHistoricalY()MotionEvent#getHistoricalPressure()MotionEvent#getHistoricalAxisValue()
Handballenerkennung
Wenn Nutzer mit einem Eingabestift zeichnen, schreiben oder mit Ihrer App interagieren, berühren sie manchmal das Display mit der Handfläche. Das Touch-Ereignis (auf ACTION_DOWN oder ACTION_POINTER_DOWN festgelegt) kann an Ihre App gemeldet werden, bevor das System die unbeabsichtigte Berührung mit der Handfläche erkennt und ignoriert.
Unter Android werden Handflächen-Touch-Ereignisse durch Senden eines MotionEvent abgebrochen. Wenn Ihre App ACTION_CANCEL empfängt, brechen Sie die Geste ab. Wenn Ihre App ACTION_POINTER_UP empfängt, prüfen Sie, ob FLAG_CANCELED festgelegt ist. Wenn ja, brechen Sie 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. Bei niedrigeren Android-Versionen wird das Flag jedoch nicht festgelegt.
Android 12
Unter Android 12 (API-Level 32) und niedriger ist die Erkennung der Handballenabweisung nur für Touch-Ereignisse mit einem einzelnen Zeiger möglich. Wenn eine Handflächenberührung der einzige Zeiger ist, bricht das System das Ereignis ab, indem es ACTION_CANCEL für das Motion-Event-Objekt festlegt. Wenn andere Zeiger nicht aktiv sind, legt das System ACTION_POINTER_UP fest, was nicht ausreicht, um die Handballenabweisung zu erkennen.
Android 13
Unter Android 13 (API‑Level 33) und höher bricht das System das Ereignis ab, indem es ACTION_CANCEL und FLAG_CANCELED für das Bewegungsereignisobjekt festlegt, wenn eine Handflächenberührung der einzige Zeiger ist. Wenn andere Zeiger nicht verfügbar sind, legt das System ACTION_POINTER_UP und FLAG_CANCELED fest.
Wenn Ihre App ein Motion-Event mit ACTION_POINTER_UP empfängt, prüfen Sie, ob FLAG_CANCELED vorhanden ist, um festzustellen, ob das Ereignis auf eine Handflächenabweisung (oder eine andere Ereignisabbrechung) hinweist.
Notizen-Apps
ChromeOS hat einen speziellen Intent, der registrierte Notizen-Apps für Nutzer sichtbar macht. Wenn Sie eine App als Notizen-App registrieren möchten, fügen Sie Ihrem 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-Notizen-App 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, in der das erste angehängte Bild als Hintergrundbild verwendet wird, und in einen Modus wechseln, in dem der Nutzer mit einem Eingabestift auf dem Bildschirm zeichnen kann.
Notiz-Intents ohne Stylus testen
So testen Sie, ob eine App ohne aktiven Eingabestift korrekt auf Notiz-Intents reagiert: Verwenden Sie dazu die folgende Methode, um die Notizoptionen unter ChromeOS anzuzeigen:
- In den Entwicklermodus wechseln und das Gerät beschreibbar machen
- Drücken Sie Strg + Alt + F2, um ein Terminal zu öffnen.
- Führen Sie den Befehl
sudo vi /etc/chrome_dev.confaus - Drücken Sie
i, um die Datei zu bearbeiten, und fügen Sie--ash-enable-palettein einer neuen Zeile am Ende der Datei hinzu. - Drücken Sie zum Speichern die Esc-Taste, geben Sie :, w, q ein und drücken Sie die Eingabetaste.
- Drücken Sie Strg + Alt + F1, um zur regulären ChromeOS-Benutzeroberfläche zurückzukehren.
- Melden Sie sich ab und wieder an
Im Ablagebereich sollte jetzt ein Stiftmenü angezeigt werden:
- Tippen Sie in der Ablage auf die Stift-Schaltfläche und wählen Sie Neue Notiz aus. Dadurch sollte eine leere Zeichennotiz geöffnet werden.
- Erstelle einen Screenshot. Wählen Sie im Ablagefach Stift-Schaltfläche > Bildschirm aufnehmen 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 soll.
Unterstützung für Maus und Touchpad
Die meisten Apps müssen in der Regel nur drei Ereignisse für große Displays verarbeiten: Rechtsklick, Hover und Drag-and-drop.
Rechtsklicken
Alle Aktionen, die dazu führen, dass in einer App ein Kontextmenü angezeigt wird, z. B. langes Berühren eines Listenelements, sollten auch auf Rechtsklickereignisse reagieren.
Um Rechtsklick-Ereignisse zu verarbeiten, müssen Apps ein 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
Durch die Verarbeitung von Hover-Ereignissen können Sie das Layout Ihrer App optimieren und die Nutzerfreundlichkeit verbessern. Das gilt insbesondere für benutzerdefinierte-Komponenten:
Die beiden häufigsten Beispiele hierfür sind:
- Nutzer darauf hinweisen, ob ein Element interaktiv ist, z. B. durch Ändern des Mauszeigersymbols, wenn es anklickbar oder bearbeitbar ist
- Visuelles Feedback für Elemente in einer großen Liste oder einem großen Raster hinzufügen, wenn der Mauszeiger darauf bewegt wird
Drag-and-drop
In einer Umgebung mit Mehrfenstermodus erwarten Nutzer, dass sie Elemente per Drag-and-drop zwischen Apps verschieben können. Das gilt für Computer sowie für Tablets, Smartphones und Faltgeräte im Splitscreen-Modus.
Überlegen Sie, ob Nutzer wahrscheinlich Elemente in Ihre App ziehen. Bei Bildbearbeitungsprogrammen ist beispielsweise davon auszugehen, dass Nutzer Fotos in die App ziehen, bei Audioplayern, dass sie Audiodateien in die App ziehen, und bei Zeichenprogrammen, dass sie Fotos in die App ziehen.
Informationen zum Hinzufügen von 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
- Denken Sie daran, die Berechtigung mit
requestDragAndDropPermissions()anzufordern, um auf Elemente zuzugreifen, die von außerhalb der App hineingezogen wurden. Ein Element muss das Flag
View.DRAG_FLAG_GLOBALhaben, damit es in andere Anwendungen gezogen werden kann.Weitere Informationen finden Sie unter Drag-Vorgang starten.
Erweiterte Unterstützung für Zeiger
Apps, die eine erweiterte Verarbeitung von Maus- und Touchpad-Eingaben erfordern, sollten einen-Modifikator (pointerInput) 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}" } } } } ) } }
Untersuchen Sie das PointerEvent-Objekt, um Folgendes zu ermitteln:
PointerType: Maus, Eingabestift, Touch usw. vonPointerEvent#changesPointerEventType: Zeigeraktionen wie Drücken, Bewegen, Scrollen und Loslassen
Controller
Einige Android-Geräte mit großem Display unterstützen bis zu vier Controller. Verwende die Standard-APIs für Android-Gamecontroller, um Gamecontroller zu verarbeiten (siehe Gamecontroller unterstützen).
Die Tasten des Controllers werden nach einer gemeinsamen Zuordnung gemeinsamen Werten zugeordnet. Allerdings folgen nicht alle Hersteller von Controllern denselben Zuordnungskonventionen. Sie können die Nutzerfreundlichkeit deutlich verbessern, wenn Sie Nutzern die Auswahl verschiedener beliebter Controller-Mappings ermöglichen. Weitere Informationen findest du unter Gamepad-Tastendrücke verarbeiten.
Eingabeübersetzungsmodus
In ChromeOS ist standardmäßig ein Modus für die Eingabeübersetzung aktiviert. Bei den meisten Android-Apps sorgt dieser Modus dafür, dass die Apps 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 die Zuordnung von Rohkoordinaten des Displays zu Fensterkoordinaten. Im Allgemeinen müssen App-Entwickler keines dieser Verhaltensweisen selbst implementieren.
Wenn eine App benutzerdefiniertes Eingabeverhalten implementiert, z. B. eine benutzerdefinierte Zwei-Finger-Touchpad-Geste, oder 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" />