คอมโพสิเบิลจำนวนมากรองรับการแตะหรือคลิกในตัว และมี 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
ซึ่งจะวาดภาพกระเพื่อมโดยค่าเริ่มต้นเมื่อผู้ใช้แตะ Composable ดูวิธีปรับแต่งเหล่านี้ได้ในหน้าการจัดการการโต้ตอบของผู้ใช้- อนุญาตให้บริการการช่วยเหลือพิเศษโต้ตอบกับองค์ประกอบโดยการตั้งค่าข้อมูลเชิงความหมาย
- รองรับการโต้ตอบด้วยแป้นพิมพ์หรือจอยสติ๊กโดยอนุญาตให้โฟกัสและกด
Enter
หรือตรงกลางของปุ่มบังคับทิศทางเพื่อโต้ตอบ - ทำให้องค์ประกอบวางเมาส์เหนือได้ เพื่อให้ตอบสนองต่อเมาส์หรือสไตลัสที่วางเหนือองค์ประกอบ
กดค้างไว้เพื่อแสดงเมนูตามบริบท
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
โดยตรงได้ ดังนี้
@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 อีกครั้งโดยอัตโนมัติเพื่อให้แน่ใจว่ามีการเรียกใช้การเรียกกลับที่ถูกต้องเมื่อผู้ใช้แตะภาพหน้าจอ
แตะสองครั้งเพื่อซูม
บางครั้ง 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 ปิดอยู่
- ทำความเข้าใจท่าทางสัมผัส
- Material Design 2 ในเครื่องมือเขียน
- Kotlin สำหรับ Jetpack Compose