Rotierende Eingabe mit „Compose“

Drehknopf bezieht sich auf Eingaben über Teile Ihrer Smartwatch, die sich drehen. Im Durchschnitt interagieren Nutzer nur wenige Sekunden mit ihrer Smartwatch. Sie können die Nutzerfreundlichkeit verbessern, indem Sie einen Drehknopf verwenden, mit dem Nutzer schnell verschiedene Aufgaben erledigen können.

Die drei Hauptquellen für den Drehknopf bei den meisten Smartwatches sind die drehbare Taste an der Seite (RSB) und entweder ein physischer Rand oder ein Touchscreen, d. h. ein kreisförmiger Touchbereich um den Bildschirm. Das erwartete Verhalten kann je nach Eingabetyp variieren. Achten Sie jedoch darauf, die Drehknopf-Eingabe für alle wichtigen Interaktionen zu unterstützen.

Scrollen

Die meisten Nutzer erwarten, dass Apps das Scrollen unterstützen. Während der Inhalt auf dem Bildschirm scrollt, geben Sie den Nutzern visuelles Feedback als Reaktion auf Drehknopfinteraktionen. Visuelles Feedback kann Positionsanzeigen für das vertikale Scrollen oder Seitenanzeigen umfassen.

ScalingLazyColumn und Picker unterstützen standardmäßig die Scrollgeste, sofern Sie diese Komponenten in einer Scaffold platzieren müssen. Scaffold enthält die grundlegende Layoutstruktur für Wear OS-Apps und hat bereits einen Slot für einen Bildlaufindikator. Um den Fortschritt des Scrollens anzuzeigen, erstellen Sie einen Positionsindikator basierend auf dem Listenstatusobjekt, wie im folgenden Code-Snippet gezeigt:

val listState = rememberScalingLazyListState()
Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = listState)
    }
) {
    // ...
}

Sie können ein Anpassen-Verhalten für ScalingLazyColumn mit ScalingLazyColumnDefaults.snapFlingBehavior konfigurieren, wie im folgenden Code-Snippet gezeigt:

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

    val state = rememberScalingLazyListState()
    ScalingLazyColumn(
        modifier = Modifier.fillMaxWidth(),
        state = state,
        flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state = state)
    ) {
        // Content goes here
        // ...
    }
}

Benutzerdefinierte Aktionen

Sie können auch benutzerdefinierte Aktionen erstellen, die in Ihrer App auf die Drehknopf-Eingabe reagieren. So können Sie beispielsweise in einer Medien-App mit dem Drehknopf heran- und herauszoomen oder die Lautstärke regeln.

Wenn Ihre Komponente keine Scroll-Ereignisse wie die Lautstärkeregelung nativ unterstützt, können Sie Scroll-Ereignisse 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 Rückruf, der zum Verarbeiten von Drehrad-Scrollereignissen verwendet wird.

// 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)
    }
}

Zur Vereinfachung werden im vorherigen Beispiel Pixelwerte verwendet, die bei tatsächlicher Verwendung wahrscheinlich zu empfindlich sind.

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(),
) { ... }