Composable จำนวนมากรองรับการแตะหรือการคลิกในตัว และมีแท็ก
onClick
แลมบ์ดา ตัวอย่างเช่น คุณสามารถสร้าง Surface
ที่คลิกได้ซึ่ง
มีลักษณะการทำงานของดีไซน์ Material ทั้งหมดที่เหมาะสำหรับการโต้ตอบกับพื้นผิว:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
แต่การคลิกไม่ได้เป็นเพียงวิธีเดียวที่ผู้ใช้สามารถโต้ตอบกับ Composable ได้ หน้านี้ เน้นที่ท่าทางสัมผัสที่เกี่ยวข้องกับตัวชี้อันเดียว โดยตำแหน่งของ ตัวชี้ดังกล่าวไม่มีนัยสำคัญในการจัดการเหตุการณ์นั้น ดังต่อไปนี้ ตารางจะแสดงประเภทของท่าทางสัมผัสต่อไปนี้
ท่าทางสัมผัส |
คำอธิบาย |
แตะ (หรือคลิก) |
ตัวชี้เลื่อนลงแล้วขึ้น |
แตะสองครั้ง |
ตัวชี้เลื่อนลง ขึ้น ลง ขึ้น |
กดค้าง |
ตัวชี้ไม่ทำงานและถือไว้เป็นเวลานานขึ้น |
สื่อ |
ตัวชี้ไม่ทำงาน |
ตอบสนองต่อการแตะหรือคลิก
clickable
คือตัวแก้ไขที่ใช้กันโดยทั่วไปซึ่งทำให้ Composable ตอบสนองต่อ
แตะหรือคลิก ตัวแก้ไขนี้ยังเพิ่มคุณลักษณะอื่นๆ เช่น การสนับสนุนสำหรับ
โฟกัส เมาส์และสไตลัสลอยอยู่ และสัญญาณบอกสถานะแบบปรับแต่งได้เมื่อ
กดแล้ว เครื่องปรับจะตอบสนองต่อ "การคลิก" ในความหมายกว้างที่สุดของคำนั้น ไม่ใช่
โดยใช้เมาส์หรือนิ้วเท่านั้น แต่ยังคลิกเหตุการณ์ผ่านการป้อนข้อมูลด้วยแป้นพิมพ์หรือเมื่อ
โดยใช้บริการการช่วยเหลือพิเศษ
ให้นึกถึงตารางกริดรูปภาพซึ่งมีรูปภาพแสดงแบบเต็มหน้าจอเมื่อผู้ใช้ คลิกที่คำนั้น:
คุณเพิ่มตัวแก้ไข 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
ซึ่งจะวาดระลอกคลื่นโดยค่าเริ่มต้นเมื่อ ผู้ใช้แตะ Composable ดูวิธีปรับแต่งการตั้งค่าเหล่านี้ได้ในการจัดการผู้ใช้ การโต้ตอบ- อนุญาตให้บริการการเข้าถึงโต้ตอบกับองค์ประกอบโดยการตั้งค่า อรรถศาสตร์
- รองรับการโต้ตอบกับแป้นพิมพ์หรือจอยสติ๊กโดยอนุญาตให้โฟกัสและการกด
Enter
หรือกึ่งกลางของ D-pad เพื่อโต้ตอบ - ทำให้องค์ประกอบวางเมาส์เหนือองค์ประกอบได้ เพื่อให้ตอบสนองต่อเมาส์หรือสไตลัสที่ลอยอยู่ เหนือสิ่งนั้น
กดค้างไว้เพื่อแสดงเมนูตามบริบทตามบริบท
combinedClickable
ช่วยให้คุณเพิ่มลักษณะการทำงานของการแตะ 2 ครั้งหรือกดค้างได้ใน
นอกเหนือจากพฤติกรรมการคลิกปกติ คุณสามารถใช้ 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
ปิด Composable ด้วยการแตะ Scrim
ในตัวอย่างด้านบน clickable
และ combinedClickable
เพิ่ม
กับ Composable โดยจะแสดงสัญญาณบอกสถานะการโต้ตอบ
ตอบสนองต่อการวางเมาส์เหนือ รวมถึงการสนับสนุนการโฟกัส แป้นพิมพ์ และการช่วยเหลือพิเศษ แต่
พฤติกรรมพิเศษนี้อาจไม่เป็นที่ต้องการเสมอไป
ลองดูที่หน้าจอรายละเอียดรูปภาพ พื้นหลังควรเป็นแบบกึ่งโปร่งใส และผู้ใช้ควรสามารถแตะพื้นหลังนั้นเพื่อปิดหน้าจอรายละเอียดได้
ในกรณีนี้ พื้นหลังดังกล่าวไม่ควรมีภาพบ่งชี้
การโต้ตอบ ไม่ควรตอบสนองต่อการวางเมาส์ ไม่ควรมุ่งเน้น และ
การตอบสนองต่อเหตุการณ์เกี่ยวกับแป้นพิมพ์และการช่วยเหลือพิเศษจะแตกต่างจาก
Composable คุณยกเลิกตัวเลือกดังกล่าวแทนการพยายามปรับลักษณะการทำงานของ 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
คุณจะส่ง lambda ได้ onClose
ช่วงเวลานี้
เรียกใช้ lambda อีกครั้งโดยอัตโนมัติ เพื่อให้แน่ใจว่ามีการเรียก Callback ที่ถูกต้อง
เมื่อผู้ใช้แตะ Scrim
แตะสองครั้งเพื่อซูม
บางครั้ง clickable
และ combinedClickable
มีข้อมูลไม่เพียงพอ
โต้ตอบกับการโต้ตอบด้วยวิธีที่ถูกต้อง ตัวอย่างเช่น Composable อาจ
ต้องการสิทธิ์เข้าถึงตำแหน่งภายในขอบเขตของ Composable ซึ่งการโต้ตอบ
ก็เกิดขึ้น
ลองดูที่หน้าจอรายละเอียดของภาพอีกครั้ง แนวทางปฏิบัติที่ดีที่สุดคือ สามารถซูมรูปภาพได้โดยแตะ 2 ครั้ง:
ตามที่คุณเห็นในวิดีโอ การซูมเข้าจะเกิดขึ้นรอบๆ ตำแหน่งการแตะ
กิจกรรม ผลที่ได้จะต่างออกไปเมื่อเราซูมเข้าไปทางด้านซ้ายของรูปภาพ
เทียบกับส่วนที่เหมาะสม เราสามารถใช้ตัวปรับแต่ง 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 ปิดอยู่
- ทำความเข้าใจท่าทางสัมผัส
- ดีไซน์ Material 2 ใน Compose
- Kotlin สำหรับ Jetpack Compose