Input dari alat rotasi dengan Compose

Input dari alat rotasi mengacu pada input dari smartwatch yang berputar atau berotasi. Rata-rata, pengguna hanya menghabiskan beberapa detik untuk berinteraksi dengan smartwatch. Anda dapat meningkatkan pengalaman pengguna menggunakan input dari alat rotasi agar pengguna dapat menyelesaikan berbagai tugas dengan cepat.

Tiga sumber utama input dari alat rotasi pada sebagian besar smartwatch meliputi tombol samping yang berputar (RSB), dan bingkai fisik atau bingkai sentuh, yang merupakan zona sentuh melingkar di sekitar layar. Meskipun perilaku yang diharapkan dapat berbeda-beda berdasarkan jenis input, pastikan input dari alat rotasi untuk semua interaksi penting dapat didukung.

Scroll

Sebagian besar pengguna berharap aplikasi mendukung gestur scroll. Saat konten di-scroll di layar, berikan masukan visual kepada pengguna sebagai respons terhadap interaksi putar. Masukan visual dapat menyertakan indikator posisi untuk scroll vertikal atau indikator halaman.

Implementasikan scroll dari alat rotasi menggunakan Compose untuk Wear OS. Contoh ini menjelaskan aplikasi dengan scaffold dan ScalingLazyColumn yang di-scroll secara vertikal. Scaffold menyediakan struktur tata letak dasar untuk aplikasi Wear OS dan telah dilengkapi slot untuk indikator scroll. Untuk menampilkan progres scroll, buat indikator posisi berdasarkan objek status daftar. Tampilan yang dapat di-scroll, termasuk ScalingLazyColumn, sudah memiliki status dapat di-scroll untuk menambahkan input dari alat rotasi. Untuk menerima peristiwa scroll dari alat rotasi, lakukan hal berikut:

  1. Minta fokus secara eksplisit menggunakan FocusRequester.
  2. Tambahkan pengubah onRotaryScrollEvent untuk menangkap peristiwa yang dihasilkan sistem saat pengguna memutar kenop jam atau memutar bingkai. Setiap peristiwa putar memiliki nilai piksel yang ditetapkan dan akan men-scroll secara vertikal atau horizontal. Pengubah juga memiliki callback untuk menunjukkan apakah peristiwa digunakan atau tidak, dan menghentikan propagasi peristiwa ke induknya saat digunakan.
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
    ) { ... }
}

Nilai diskret

Gunakan interaksi putar untuk menyesuaikan nilai terpisah juga, seperti menyesuaikan kecerahan pada setelan atau memilih angka dalam alat pilih waktu saat menyetel alarm.

Serupa dengan ScalingLazyColumn, alat pilih, penggeser, stepper, dan composable lainnya harus memiliki fokus untuk menerima input dari alat rotasi. Untuk beberapa target yang dapat di-scroll di layar, seperti jam dan menit pada alat pilih waktu, buat FocusRequester untuk setiap target dan tangani perubahan fokus yang sesuai saat pengguna mengetuk salah satu jam atau menit.

@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()
    }
}

Tindakan kustom

Anda juga bisa membuat tindakan khusus yang merespons input dari alat rotasi di aplikasi Anda. Misalnya, gunakan input dari alat rotasi untuk memperbesar dan memperkecil atau mengontrol volume di aplikasi media.

Jika komponen Anda tidak mendukung peristiwa scroll seperti kontrol volume secara native, Anda dapat menangani peristiwa scroll sendiri.

// VolumeScreen.kt

val focusRequester: FocusRequester = remember { FocusRequester() }

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

Membuat status kustom yang dikelola di model tampilan, dan callback kustom yang digunakan untuk memproses peristiwa scroll putar.

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

Agar lebih praktis, contoh sebelumnya menggunakan nilai piksel yang jika benar-benar digunakan justru akan cenderung terlalu sensitif.

Gunakan callback setelah Anda menerima peristiwa, seperti yang ditunjukkan dalam cuplikan berikut.

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

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

Referensi lainnya

Pertimbangkan untuk menggunakan Horologist, project open source Google yang menyediakan kumpulan library Wear yang melengkapi fungsi yang disediakan oleh Compose untuk Wear OS dan API Wear OS lainnya. Horologist menyediakan implementasi untuk kasus penggunaan lanjutan dan banyak detail khusus perangkat.

Misalnya, sensitivitas berbagai sumber input dari alat rotasi dapat berbeda-beda. Untuk transisi antar-nilai yang lebih lancar, Anda dapat membatasi kapasitas atau menambahkan snap atau animasi untuk transisi. Dengan menerapkan cara ini, kecepatan putar akan terasa lebih alami bagi pengguna. Horologist menyertakan pengubah untuk komponen yang dapat di-scroll dan untuk nilai terpisah. Rilis ini juga mencakup utilitas untuk menangani fokus dan library UI Audio untuk mengimplementasikan kontrol volume dengan haptik.

Untuk mengetahui informasi selengkapnya, lihat Horologist di GitHub.