旋轉輸入是指轉動或旋轉手錶零件來輸入內容。使用者與手錶互動的時間平均只有幾秒鐘,因此建議您使用旋轉輸入機制,讓使用者快速完成各項工作,打造更優質的使用者體驗。
多數手錶上的三個主要旋轉輸入來源,包括側邊旋轉按鈕 (RSB)、實體邊框或觸控邊框,後者是指螢幕周圍的圓形觸控區。即使預期的行為可能因輸入類型而有所不同,請務必為所有重要互動方式支援旋轉輸入。
捲動
大多數使用者會預期應用程式支援捲動手勢。使用者在畫面上捲動內容時,請提供回應旋轉互動動作的視覺回饋。視覺回饋可包括用於垂直捲動的位置指標或頁面指標。
使用 Compose for Wear OS 實作旋轉捲動。以下範例中的應用程式具有 Scaffold 以及可垂直捲動的 ScalingLazyColumn
。Scaffold 可為 Wear OS 應用程式提供基本的版面配置結構,且已有捲動指標專用的版位。如要顯示捲動進度,請根據清單狀態物件建立位置指標。可捲動的檢視區塊 (包括 ScalingLazyColumn
) 已具備用於新增旋轉輸入的可捲動狀態。如要接收旋轉捲動事件,請執行下列操作:
使用
FocusRequester
明確要求焦點。使用HierarchicalFocusCoordinator
適用於較複雜的情況,例如多個情況HorizontalPager
中的ScalingLazyColumns
物件。新增
onRotaryScrollEvent
修飾符,攔截系統在使用者轉動錶冠或旋轉邊框時產生的事件。每個旋轉事件都有已設定的像素值,且會垂直或水平捲動。修飾符也具有指出事件是否已取用的回呼,且會在已取用時停止將事件傳播至其父項。
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() .fillMaxSize(), state = listState ) { // Content goes here // ... } }
離散值
您也可以使用旋轉互動動作調整離散值,例如在設定中調整亮度,或是在設定鬧鐘時選取時間選擇器中的數字。
與 ScalingLazyColumn
類似,無論是選擇器、滑桿、步驟顯示器還是其他可組合函式,皆須具備焦點才能接收旋轉輸入。如果畫面上有多個可捲動的目標 (例如時間選擇器的小時和分鐘),請為每個目標建立 FocusRequester
,並根據使用者輕觸小時或分鐘處理焦點變更。
var selectedColumn by remember { mutableIntStateOf(0) } val hoursFocusRequester = remember { FocusRequester() } val minutesRequester = remember { FocusRequester() } // ... Scaffold(modifier = Modifier.fillMaxSize()) { Row( // ... // ... ) { // ... Picker( readOnly = selectedColumn != 0, modifier = Modifier.size(64.dp, 100.dp) .onRotaryScrollEvent { coroutineScope.launch { hourState.scrollBy(it.verticalScrollPixels) } true } .focusRequester(hoursFocusRequester) .focusable(), onSelected = { selectedColumn = 0 }, // ... // ... ) // ... Picker( readOnly = selectedColumn != 1, modifier = Modifier.size(64.dp, 100.dp) .onRotaryScrollEvent { coroutineScope.launch { minuteState.scrollBy(it.verticalScrollPixels) } true } .focusRequester(minutesRequester) .focusable(), onSelected = { selectedColumn = 1 }, // ... // ... ) LaunchedEffect(selectedColumn) { listOf( hoursFocusRequester, minutesRequester )[selectedColumn] .requestFocus() } } }
自訂動作
您也可以建立自訂動作,對應用程式中的旋轉輸入內容做出回應。例如使用旋轉輸入放大及縮小畫面,或控制媒體應用程式中的音量。
如果元件原本不支援捲動事件 (例如音量控制),您可以自行處理捲動事件。
// VolumeScreen.kt
val focusRequester: FocusRequester = remember { FocusRequester() }
Column(
modifier = Modifier
.fillMaxSize()
.onRotaryScrollEvent {
// handle rotary scroll events
true
}
.focusRequester(focusRequester)
.focusable(),
) { ... }
建立透過檢視模型管理的自訂狀態,以及用來處理旋轉捲動事件的自訂回呼。
// 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)
}
}
為求簡單起見,上方範例使用了像素值 (如果實際使用可能會導致靈敏度過高)。
在接收到事件後使用回呼,如以下程式碼片段所示。
val focusRequester: FocusRequester = remember { FocusRequester() }
val volumeState by volumeViewModel.volumeState.collectAsState()
Column(
modifier = Modifier
.fillMaxSize()
.onRotaryScrollEvent {
volumeViewModel
.onVolumeChangeByScroll(it.verticalScrollPixels)
true
}
.focusRequester(focusRequester)
.focusable(),
) { ... }
其他資源
建議使用 Horologist,這項 Google 開放原始碼專案提供一組 Wear 程式庫,可補充 Compose for Wear OS 和其他 Wear OS API 提供的功能。Horologist 提供了進階用途的實作方式,以及許多裝置專屬的詳細資料。
舉例來說,不同旋轉輸入來源的靈敏度可能會有差異。為了在兩個值之間順利轉換,您可以限制頻率、加入貼齊設定或轉場動畫。這樣一來,使用者會感覺轉動速度更加自然。Horologist 內含可捲動元件和獨離散值適用的修飾符,還提供用於處理焦點的公用程式,以及透過觸覺技術實作音量控制的音訊 UI 程式庫。
詳情請參閱 GitHub 的 Horologist。
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 變更焦點行為
- 透過 Jetpack Compose 新增鍵盤、滑鼠、觸控板和觸控筆支援功能
- Compose for Wear OS 程式碼研究室