Rotierende Eingabe mit „Compose“

Eine Dreheingabe ist die Eingabe von Teilen Ihrer Uhr, die sich drehen oder drehen. Im Durchschnitt verbringen Nutzer nur wenige Sekunden mit ihrer Uhr. Mit der Dreheingabe können Sie verschiedene Aufgaben schnell und einfach erledigen.

Die drei Hauptquellen für den Drehknopf bei den meisten Uhren sind die rotierende seitliche Taste (RSB) und entweder ein physischer Glasrand oder ein Touchrand – ein kreisförmiger Berührungsbereich um den Bildschirm. Das erwartete Verhalten kann je nach Art der Eingabe variieren. Achten Sie aber darauf, den Drehknopf für alle wichtigen Interaktionen zu unterstützen.

Scrollen

Die meisten Nutzer erwarten, dass Apps die Scroll-Geste unterstützen. Geben Sie den Nutzenden visuelles Feedback als Reaktion auf Drehbewegungen, während der Inhalt auf dem Bildschirm scrollt. Visuelles Feedback kann Positionsanzeigen für vertikales Scrollen oder Seitenanzeigen umfassen.

Drehscrollen mit Compose für Wear OS implementieren Dieses Beispiel beschreibt eine App mit einem Gerüst und einem ScalingLazyColumn, das vertikal scrollt. Das Gerüst bietet die grundlegende Layoutstruktur für Wear OS-Apps und hat bereits einen Platz für eine Scrollanzeige. Um den Scrollfortschritt anzuzeigen, erstellen Sie einen Positionsindikator, der auf dem Listenstatusobjekt basiert. Scrollbare Ansichten, einschließlich ScalingLazyColumn, haben bereits einen scrollbaren Status, um einen Drehknopf hinzuzufügen. So empfangen Sie Dreh-Scroll-Ereignisse:

  1. Fordere den Fokus explizit mit FocusRequester an.
  2. Fügen Sie den Modifikator onRotaryScrollEvent hinzu, um Ereignisse abzufangen, die das System generiert, wenn ein Nutzer die Krone dreht oder den Glasrand dreht. Jedes Drehereignis hat einen festgelegten Pixelwert und scrollt vertikal oder horizontal. Der Modifikator hat auch einen Callback, der angibt, ob das Ereignis verarbeitet wird, und stoppt die Weitergabe der Ereignisse an die übergeordneten Elemente.
val listState = rememberScalingLazyListState()

Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = listState)
    }
) {

    val focusRequester = rememberActiveFocusRequester()
    val coroutineScope = rememberCoroutineScope()

    ScalingLazyColumn(
        modifier = Modifier
            .onRotaryScrollEvent {
                coroutineScope.launch {
                    listState.scrollBy(it.verticalScrollPixels)

                    listState.animateScrollBy(0f)
                }
                true
            }
            .focusRequester(focusRequester)
            .focusable(),
        state = listState
    ) { ... }
}

Diskrete Werte

Mit Drehbewegungen können Sie auch diskrete Werte anpassen, z. B. die Helligkeit in den Einstellungen oder die Zahlen in der Zeitauswahl beim Einstellen eines Weckers.

Ähnlich wie bei ScalingLazyColumn müssen Picker, Schieberegler, Stepper und andere zusammensetzbare Funktionen im Fokus stehen, um Drehbewegungen zu empfangen. Wenn es auf dem Bildschirm mehrere scrollbare Ziele gibt, z. B. die Stunden und Minuten in der Zeitauswahl, musst du für jedes Ziel ein FocusRequester erstellen und die Fokusänderung entsprechend behandeln, wenn der Nutzer auf Stunden oder Minuten tippt.

@Composable
fun TimePicker() {
    var selectedColumn by remember { mutableStateOf(0) }
    val focusRequester1 = remember { FocusRequester() }
    val focusRequester2 = remember { FocusRequester() }

    Row {
       Picker(...)
       Picker(...)
    }

    LaunchedEffect(selectedColumn) {
        listOf(focusRequester1,
               focusRequester2)[selectedColumn]
            .requestFocus()
    }
}

Benutzerdefinierte Aktionen

Sie können auch benutzerdefinierte Aktionen erstellen, die auf den Drehknopf in Ihrer App reagieren, z. B. zum Heran- und Herauszoomen oder zum Steuern der Lautstärke in einer Medien-App.

Wenn Ihre Komponente Scrollereignisse wie die Lautstärkeregelung nicht nativ unterstützt, können Sie Scrollereignisse selbst verarbeiten.

// VolumeScreen.kt

val focusRequester: FocusRequester = remember { FocusRequester() }

Column(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            // handle rotary scroll events
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) { ... }

Erstellen Sie einen benutzerdefinierten Status, der im Ansichtsmodell verwaltet wird, und einen benutzerdefinierten Callback, mit dem Dreh-Scroll-Ereignisse verarbeitet werden.

// VolumeViewModel.kt

object VolumeRange(
    public val max: Int = 10
    public val min: Int = 0
)

val volumeState: MutableStateFlow<Int> = ...

fun onVolumeChangeByScroll(pixels: Float) {
    volumeState.value = when {
        pixels > 0 -> min (volumeState.value + 1, VolumeRange.max)
        pixels < 0 -> max (volumeState.value - 1, VolumeRange.min)
    }
}

Der Einfachheit halber werden im vorherigen Beispiel Pixelwerte verwendet, die wahrscheinlich zu empfindlich sind, wenn sie tatsächlich verwendet werden.

Verwenden Sie den Callback, sobald Sie die Ereignisse erhalten haben, wie im folgenden Snippet gezeigt.

val focusRequester: FocusRequester = remember { FocusRequester() }
val volumeState by volumeViewModel.volumeState.collectAsState()

Column(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            volumeViewModel
                .onVolumeChangeByScroll(it.verticalScrollPixels)
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) { ... }

Weitere Informationen

Wir empfehlen Horologist, ein Open-Source-Projekt von Google, das eine Reihe von Wear-Bibliotheken bietet, die die Funktionen von Compose für Wear OS und andere Wear OS APIs ergänzen. Der Horologist bietet die Implementierung für erweiterte Anwendungsfälle und viele gerätespezifische Details.

So kann die Empfindlichkeit der verschiedenen Drehknopfquellen variieren. Für einen flüssigeren Übergang zwischen Werten können Sie eine Ratenbegrenzung festlegen oder ein Andocken oder Animationen für den Übergang hinzufügen. So wirkt das Drehen für die Nutzenden natürlicher. Der Horologe bietet Modifikatoren für scrollbare Komponenten und für diskrete Werte. Er enthält auch Dienstprogramme zur Verwaltung des Fokus und eine Audio-UI-Bibliothek zur Implementierung der Lautstärkeregelung mit Haptik.

Weitere Informationen finden Sie unter Horologist auf GitHub.