Wprowadzanie obrotowe z funkcją tworzenia


Pokrętło to dane pochodzące z elementów zegarka, które obracają się lub obracają wokół własnej osi. Użytkownicy poświęcają na obsługę zegarka średnio tylko kilka sekund. Możesz zwiększyć wygodę użytkowników, umożliwiając im szybkie wykonywanie różnych zadań za pomocą elementów sterujących obrotowych.

W większości zegarków 3 główne źródła obrotowego wejścia to obracający się przycisk boczny (RSB) oraz ramka dotykowa lub ramka dotykowa, czyli okrągła strefa dotykowa wokół ekranu. Chociaż oczekiwane działanie może się różnić w zależności od typu danych wejściowych, pamiętaj, aby obsługiwać dane wejściowe z urządzenia obrotowego we wszystkich istotnych interakcjach.

Przewiń

Większość użytkowników oczekuje, że aplikacje będą obsługiwać gest przewijania. Podczas przewijania treści na ekranie wyświetlaj użytkownikom wizualne informacje zwrotne w reakcji na interakcje z elementem obrotowym. Wizualne informacje zwrotne mogą obejmować wskaźniki przewijania w przypadku przewijania pionowego lub wskaźniki stron.

Komponenty ScalingLazyColumn, TransformingLazyColumnPicker obsługują domyślnie gest przewijania, o ile tylko musisz umieścić te komponenty w komponencie AppScaffoldScreenScaffold oraz przekazywać stan listy między komponentem ScreenScaffold a komponentem, takim jak TransformingLazyColumn.

AppScaffoldScreenScaffold zapewniają podstawową strukturę układu dla aplikacji na Wear OS i zawierają już slot dla wskaźnika przewijania z domyślną implementacją. Aby dostosować postęp przewijania, utwórz wskaźnik przewijania na podstawie obiektu stanu listy, jak pokazano w tym fragmencie kodu:

val listState = rememberTransformingLazyColumnState()
ScreenScaffold(
    scrollState = listState,
    scrollIndicator = {
        ScrollIndicator(state = listState)
    }
) {
    // ...
}

Aby skonfigurować zachowanie przyciągania dla ScalingLazyColumn, użyj elementu ScalingLazyColumnDefaults.snapFlingBehavior, jak pokazano w tym fragmencie kodu:

val listState = rememberScalingLazyListState()
ScreenScaffold(
    scrollState = listState,
    scrollIndicator = {
        ScrollIndicator(state = listState)
    }
) {

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

Działania niestandardowe

Możesz też tworzyć w aplikacji niestandardowe działania, które będą reagować na pokrętło. Na przykład możesz używać pokrętła do przybliżania i oddalania lub do sterowania głośnością w aplikacji multimedialnej.

Jeśli Twój komponent nie obsługuje natywnych zdarzeń przewijania, takich jak sterowanie głośnością, możesz samodzielnie obsługiwać zdarzenia przewijania.

// VolumeScreen.kt

val focusRequester: FocusRequester = remember { FocusRequester() }

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

Utwórz niestandardowy stan zarządzany w modelu widoku oraz niestandardową funkcję wywołania, która służy do przetwarzania zdarzeń przewijania za pomocą kółka.

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

Ze względu na prostotę w powyższym przykładzie użyto wartości pikseli, które w rzeczywistości są zbyt czułe.

Po otrzymaniu zdarzeń użyj wywołania zwrotnego, jak pokazano w tym fragmencie kodu.

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

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