Wprowadzanie obrotowe z funkcją tworzenia


Pokrętło to dane pochodzące z elementów zegarka, które się obracają. Użytkownicy poświęcają na obsługę zegarka średnio tylko kilka sekund. Możesz zwiększyć wygodę użytkownika, umożliwiając mu korzystanie z elementu sterującego obrotowego, aby szybko wykonywać różne zadania.

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