許多可組合項內建支援輕觸或點擊功能,且包括 onClick
lambda。舉例來說,您可以建立可點選的 Surface
,加入所有適合與途徑互動的 Material Design 行為:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
然而,點擊並不是使用者能與可組合項互動的唯一方式。本頁重點說明涉及單一指標的手勢,而該指標的位置對於處理該事件來說並不重要。下表列出這些類型的手勢:
手勢 |
說明 |
輕觸 (或點選) |
指標先往下再往上 |
輕觸兩下 |
指標往下、上、下、上 |
長按 |
指標下降,並保留較長的時間 |
新聞中心 |
指標下降 |
回應輕觸或點選動作
clickable
是常用的修飾符,可使可組合項回應輕觸或點選動作。這個修飾符還新增多項功能,例如支援聚焦、滑鼠和觸控筆懸停,以及可自訂的視覺指標 (按下時)。修飾符會以最寬鬆的方式回應「點擊」動作,除了滑鼠或手指,還會透過鍵盤輸入或使用無障礙服務點擊事件。
假設圖片格線,使用者點選圖片後,圖片會以全螢幕顯示:
您可以為格線中的每個項目新增 clickable
修飾符,以實作此行為:
@Composable private fun ImageGrid(photos: List<Photo>) { var activePhotoId by rememberSaveable { mutableStateOf<Int?>(null) } LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier.clickable { activePhotoId = photo.id } ) } } if (activePhotoId != null) { FullScreenImage( photo = photos.first { it.id == activePhotoId }, onDismiss = { activePhotoId = null } ) } }
clickable
修飾符還會新增其他行為:
interactionSource
和indication
,會在使用者輕觸可組合項時預設繪製漣漪效果。如要瞭解如何自訂這些內容,請參閱「處理使用者互動」頁面。- 透過設定語意資訊,允許無障礙服務與元素互動。
- 支援聚焦並按下
Enter
或 D-Pad 中心,支援鍵盤或搖桿互動。 - 將元素設為可懸停元素,使其回應滑鼠遊標懸停的滑鼠或觸控筆。
長按即可顯示內容內容選單
combinedClickable
可讓您在一般點擊行為之外,新增輕觸兩下或長按的行為。您可以使用 combinedClickable
,在使用者輕觸並按住格線圖片時顯示內容選單:
var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) } val haptics = LocalHapticFeedback.current LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier .combinedClickable( onClick = { activePhotoId = photo.id }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) contextMenuPhotoId = photo.id }, onLongClickLabel = stringResource(R.string.open_context_menu) ) ) } } if (contextMenuPhotoId != null) { PhotoActionsSheet( photo = photos.first { it.id == contextMenuPhotoId }, onDismissSheet = { contextMenuPhotoId = null } ) }
最佳做法是在使用者長按元素時加入觸覺回饋,因此程式碼片段包含 performHapticFeedback
叫用。
輕觸紗罩可關閉可組合項
在上述範例中,clickable
和 combinedClickable
會在可組合項中加入實用的功能。這類指標會顯示互動、回應懸停回應的視覺指標,包括聚焦、鍵盤和無障礙功能支援。但這樣的額外行為並非隨時理想。
再來看看圖片詳細資料畫面。背景應為半透明,且使用者應能輕觸該背景來關閉詳細資料畫面:
在這種情況下,背景不應有任何互動的視覺指標、不應回應懸停回應、不可聚焦,且其對鍵盤和無障礙功能事件的回應與一般可組合項不同。您不必嘗試調整 clickable
的行為,而是可以降至較低的抽象層級,並直接使用 pointerInput
修飾符搭配 detectTapGestures
方法:
@OptIn(ExperimentalComposeUiApi::class) @Composable private fun Scrim(onClose: () -> Unit, modifier: Modifier = Modifier) { val strClose = stringResource(R.string.close) Box( modifier // handle pointer input .pointerInput(onClose) { detectTapGestures { onClose() } } // handle accessibility services .semantics(mergeDescendants = true) { contentDescription = strClose onClick { onClose() true } } // handle physical keyboard input .onKeyEvent { if (it.key == Key.Escape) { onClose() true } else { false } } // draw scrim .background(Color.DarkGray.copy(alpha = 0.75f)) ) }
做為 pointerInput
修飾符的鍵,您會傳遞 onClose
lambda。系統會自動重新執行 lambda,確保在使用者輕觸紗罩時呼叫正確的回呼。
輕觸兩下縮放
有時候,clickable
和 combinedClickable
缺少的資訊不足,無法以正確的方式回應互動。舉例來說,可組合項可能需要存取可組合項邊界內互動位置的存取位置。
再看一次圖片詳細資料畫面。最佳做法是輕觸兩下就能放大圖片:
如影片所示,放大作業會在輕觸事件的位置附近發生。在圖片左側和右側部分放大時,結果會有所不同。我們可以搭配使用 pointerInput
修飾符與 detectTapGestures
,將輕觸位置納入計算中:
var zoomed by remember { mutableStateOf(false) } var zoomOffset by remember { mutableStateOf(Offset.Zero) } Image( painter = rememberAsyncImagePainter(model = photo.highResUrl), contentDescription = null, modifier = modifier .pointerInput(Unit) { detectTapGestures( onDoubleTap = { tapOffset -> zoomOffset = if (zoomed) Offset.Zero else calculateOffset(tapOffset, size) zoomed = !zoomed } ) } .graphicsLayer { scaleX = if (zoomed) 2f else 1f scaleY = if (zoomed) 2f else 1f translationX = zoomOffset.x translationY = zoomOffset.y } )
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 瞭解手勢
- Compose 中的質感設計 2
- 適用於 Jetpack Compose 的 Kotlin