Tạo phương thức nhập dữ liệu xoay bằng Compose

Phương thức nhập dữ liệu xoay đề cập đến dữ liệu đầu vào nhập từ các thành phần có thể xoay hoặc vặn của đồng hồ. Trung bình thì người dùng chỉ dành vài giây để tương tác với đồng hồ. Bạn có thể cải thiện trải nghiệm người dùng bằng cách sử dụng phương thức nhập dữ liệu xoay giúp người dùng nhanh chóng hoàn tất nhiều thao tác.

Có 3 nguồn nhập dữ liệu xoay chính trên hầu hết đồng hồ, trong đó có nút xoay bên hông (RSB) và một viền xoay hoặc viền cảm ứng (là vùng cảm ứng bo tròn xung quanh màn hình). Tuy hành vi dự kiến có thể thay đổi tuỳ theo loại dữ liệu đầu vào, nhưng hãy đảm bảo việc hỗ trợ phương thức nhập dữ liệu xoay cho mọi yếu tố tương tác thiết yếu.

Cuộn

Hầu hết người dùng đều muốn ứng dụng hỗ trợ cử chỉ cuộn. Khi nội dung cuộn trên màn hình, hãy cho người dùng thấy có sự phản hồi bằng hình ảnh đối với các tương tác xoay. Phản hồi bằng hình ảnh có thể là chỉ báo vị trí (để cuộn dọc) hoặc chỉ báo trang.

Triển khai tính năng cuộn xoay bằng Compose cho Wear OS. Ví dụ này mô tả một ứng dụng có bộ khung (scaffold) và ScalingLazyColumn cuộn dọc. Bộ khung cung cấp cấu trúc bố cục cơ bản cho ứng dụng Wear OS và đã có sẵn một chỗ cho chỉ báo cuộn. Để cho thấy tiến trình cuộn, hãy tạo một chỉ báo vị trí dựa trên đối tượng trạng thái của danh sách. Chế độ xem có thể cuộn (bao gồm cả ScalingLazyColumn) đã có trạng thái cuộn để thêm phương thức nhập dữ liệu xoay. Để nhận sự kiện cuộn xoay, hãy làm như sau:

  1. Yêu cầu rõ ràng tiêu điểm bằng FocusRequester.
  2. Thêm đối tượng sửa đổi onRotaryScrollEvent để chặn các sự kiện mà hệ thống tạo ra khi người dùng xoay núm vặn hoặc xoay mép. Mỗi sự kiện xoay có một giá trị điểm ảnh đã thiết lập và cuộn dọc hoặc ngang. Đối tượng sửa đổi cũng có lệnh gọi lại để cho biết liệu sự kiện có được sử dụng hay không và dừng việc truyền sự kiện cho thành phần mẹ khi được tiêu thụ.
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
    ) { ... }
}

Giá trị rời rạc

Bạn cũng có thể sử dụng tương tác xoay để điều chỉnh các giá trị rời rạc, chẳng hạn như điều chỉnh độ sáng trong chế độ cài đặt hoặc chọn số trong bộ chọn giờ để đặt chuông báo.

Tương tự như ScalingLazyColumn, bộ chọn, thanh trượt, bộ điều chỉnh tăng giảm, và các thành phần kết hợp khác cần có tiêu điểm để nhận phương thức nhập dữ liệu xoay. Trong trường hợp có nhiều mục tiêu có thể cuộn trên màn hình, chẳng hạn như giờ và phút trong bộ chọn giờ, hãy tạo FocusRequester cho từng mục tiêu và xử lý thay đổi tương ứng đối với tiêu điểm khi người dùng nhấn vào giờ hoặc phút.

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

Thao tác tuỳ chỉnh

Bạn cũng có thể tạo các thao tác tuỳ chỉnh phản hồi phương thức nhập dữ liệu xoay trong ứng dụng của mình. Ví dụ: sử dụng phương thức nhập dữ liệu xoay để phóng to và thu nhỏ hoặc để điều chỉnh âm lượng trong ứng dụng đa phương tiện.

Nếu thành phần của bạn không hỗ trợ sẵn các sự kiện cuộn (ví dụ: điều khiển âm lượng), thì bạn có thể tự xử lý các sự kiện cuộn đó.

// VolumeScreen.kt

val focusRequester: FocusRequester = remember { FocusRequester() }

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

Tạo trạng thái tuỳ chỉnh được quản lý trong mô hình chế độ xem và lệnh gọi lại tuỳ chỉnh dùng để xử lý các sự kiện cuộn xoay.

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

Nói một cách đơn giản, ví dụ trên sử dụng giá trị pixel mà nếu được sử dụng trong thực tế thì độ nhạy có thể trở nên quá cao.

Sử dụng lệnh gọi lại khi nhận được sự kiện, như trong đoạn mã sau.

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

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

Tài nguyên khác

Hãy cân nhắc sử dụng Horologist (một dự án nguồn mở của Google), nơi cung cấp bộ thư viện Wear bổ sung chức năng do Compose cho Wear OS và các API Wear OS khác cung cấp. Horologist cung cấp phương thức triển khai cho các trường hợp sử dụng nâng cao, cùng nhiều thông tin chi tiết về thiết bị.

Ví dụ: độ nhạy của các nguồn phương thức nhập dữ liệu xoay có thể khác nhau. Để quá trình chuyển đổi diễn ra suôn sẻ hơn giữa các giá trị, bạn có thể đánh giá giới hạn hoặc thêm ảnh chụp nhanh hoặc ảnh động cho quá trình chuyển đổi. Điều này cho phép chuyển đổi tốc độ để người dùng có cảm giác tự nhiên hơn. Horologist cung cấp các đối tượng sửa đổi cho các thành phần có thể cuộn và cho các giá trị rời rạc. Horologist cũng cung cấp các tiện ích để xử lý tiêu điểm và thư viện Giao diện người dùng âm thanh để triển khai chức năng điều khiển âm lượng bằng xúc giác.

Để biết thêm thông tin, hãy xem bài viết về Horologist trên GitHub.