許多可組合函式內建輕觸或點擊機制支援,且會包含
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
叫用。
輕觸 scrim 以關閉可組合函式
在上例中,clickable
和 combinedClickable
新增實用的資訊
組合功能會顯示有關互動的視覺指標
並支援焦點、鍵盤和無障礙功能。但
這種額外行為不一定是最理想的情況
我們來看看圖片詳細資料畫面。背景須為半透明 而使用者應該要能輕觸該背景來關閉詳細資料畫面:
在此情況下,該背景不應
互動時不應回應、並非可聚焦
對鍵盤和無障礙功能事件的回應
可組合函式。您不需要嘗試調整 clickable
行為,而是可以
較低抽象層級,並直接使用 pointerInput
修飾符
與 detectTapGestures
方法結合:
@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