Поворотный ввод с помощью Compose


Вращающийся ввод — это ввод данных с вращающихся или вращающихся частей ваших часов. В среднем пользователи тратят на взаимодействие со своими часами всего несколько секунд. Вы можете улучшить пользовательский опыт, используя вращающийся ввод, чтобы позволить пользователю быстро выполнять различные задачи.

Три основных способа управления поворотным устройством на большинстве часов включают вращающуюся боковую кнопку (RSB) и либо физический, либо сенсорный безель, представляющий собой круглую сенсорную зону вокруг экрана. Хотя ожидаемое поведение может различаться в зависимости от типа ввода, убедитесь, что поддерживается поворотное управление для всех основных взаимодействий.

Индикатор прокрутки

Большинство пользователей ожидают, что приложения будут поддерживать жест прокрутки. По мере прокрутки контента на экране предоставляйте пользователю визуальную обратную связь в ответ на поворотные движения. Визуальная обратная связь может включать в себя индикаторы вертикальной прокрутки или индикаторы страниц .

ScalingLazyColumn , TransformingLazyColumn и Picker поддерживают жест прокрутки по умолчанию, если поместить эти компоненты в AppScaffold и ScreenScaffold и передать состояние списка между ScreenScaffold и компонентом, например TransformingLazyColumn .

AppScaffold и ScreenScaffold предоставляют базовую структуру макета для приложений Wear OS и уже содержат слот для индикатора прокрутки с реализацией по умолчанию. Чтобы настроить ход прокрутки, создайте индикатор прокрутки на основе объекта состояния списка, как показано в следующем фрагменте кода:

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

Вы можете настроить поведение привязки для ScalingLazyColumn с помощью ScalingLazyColumnDefaults.snapFlingBehavior , как показано в следующем фрагменте кода:

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

Пользовательские действия

Вы также можете создавать пользовательские действия, реагирующие на поворотный ввод в вашем приложении. Например, используйте поворотный ввод для увеличения и уменьшения масштаба или для управления громкостью в медиаприложении.

Если ваш компонент изначально не поддерживает события прокрутки, такие как регулировка громкости, вы можете обрабатывать события прокрутки самостоятельно.

Первым шагом является создание пользовательского состояния, управляемого в модели представления, и пользовательского обратного вызова, который используется для обработки событий вращательной прокрутки.

class VolumeRange(
    val max: Int = 10,
    val min: Int = 0
)

private object VolumeViewModel {
    class MyViewModel : ViewModel() {
        private val _volumeState = mutableIntStateOf(0)
        val volumeState: State<Int>
            get() = _volumeState

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

Затем используйте обратный вызов после получения событий, как показано в следующем фрагменте.

val focusRequester: FocusRequester = remember { FocusRequester() }
val volumeViewModel: VolumeViewModel.MyViewModel =
    viewModel()
val volumeState by volumeViewModel.volumeState

TransformingLazyColumn(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            volumeViewModel.onVolumeChangeByScroll(it.verticalScrollPixels)
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) {
    // You can use volumeState here, for example:
    item {
        Text("Volume: $volumeState")
    }
}

Обратите внимание, что для простоты в предыдущем примере используются значения пикселей, которые при фактическом использовании, вероятно, будут слишком чувствительными.

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}