ตัวแก้ไขการเลื่อน
ตัวแก้ไข
verticalScroll
และ
horizontalScroll
เป็นวิธีที่ง่ายที่สุดในการอนุญาตให้ผู้ใช้เลื่อนองค์ประกอบเมื่อขอบเขตของเนื้อหามีขนาดใหญ่กว่าข้อจำกัดด้านขนาดสูงสุด โดยใช้ตัวแก้ไข verticalScroll และ horizontalScroll คุณไม่จำเป็นต้องแปลหรือชดเชยเนื้อหา
@Composable private fun ScrollBoxes() { Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .verticalScroll(rememberScrollState()) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
ScrollState
ช่วยให้คุณเปลี่ยนตำแหน่งการเลื่อนหรือรับสถานะปัจจุบันได้ หากต้องการสร้างโดยใช้พารามิเตอร์เริ่มต้น ให้ใช้
rememberScrollState()
@Composable private fun ScrollBoxesSmooth() { // Smoothly scroll 100px on first composition val state = rememberScrollState() LaunchedEffect(Unit) { state.animateScrollTo(100) } Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .padding(horizontal = 8.dp) .verticalScroll(state) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
ตัวแก้ไขพื้นที่ที่เลื่อนได้
ตัวแก้ไข scrollableArea เป็นองค์ประกอบพื้นฐานสำหรับการสร้าง
คอนเทนเนอร์ที่เลื่อนได้แบบกำหนดเอง ซึ่งจะมีการแยกข้อมูลระดับสูงกว่าตัวแก้ไข scrollable โดยจะจัดการข้อกำหนดทั่วไป เช่น การตีความเดลต้าของท่าทางสัมผัส การตัดเนื้อหา และเอฟเฟกต์การเลื่อนเกิน
แม้ว่า scrollableArea จะใช้สำหรับการติดตั้งใช้งานที่กำหนดเอง แต่โดยทั่วไปคุณควร
เลือกใช้โซลูชันสำเร็จรูป เช่น verticalScroll, horizontalScroll
หรือ Composable เช่น LazyColumn สำหรับรายการเลื่อนมาตรฐาน คอมโพเนนต์ระดับสูงเหล่านี้
จะเรียบง่ายกว่าสำหรับกรณีการใช้งานทั่วไป และสร้างขึ้นโดยใช้ scrollableArea
ความแตกต่างระหว่างตัวแก้ไข scrollableArea กับ scrollable
ความแตกต่างหลักระหว่าง scrollableArea กับ scrollable อยู่ที่วิธี
ตีความท่าทางการเลื่อนของผู้ใช้ ดังนี้
scrollable(เดลต้ารูปแบบดิบ): เดลต้าแสดงถึงการเคลื่อนไหวทางกายภาพ ของอินพุตของผู้ใช้ (เช่น การลากเคอร์เซอร์) บนหน้าจอโดยตรงscrollableArea(เดลต้าที่เน้นเนื้อหา):deltaจะกลับด้านเชิงความหมาย เพื่อแสดงการเปลี่ยนแปลงที่เลือกในตำแหน่งการเลื่อนเพื่อให้เนื้อหาปรากฏขึ้นพร้อมกับการเคลื่อนไหวของผู้ใช้ ซึ่งมักจะตรงกันข้ามกับการเคลื่อนที่ของเคอร์เซอร์
ลองนึกภาพว่า scrollable บอกวิธีที่เคอร์เซอร์เคลื่อนที่ ขณะที่ scrollableArea แปลการเคลื่อนที่ของเคอร์เซอร์นั้นเป็นวิธีที่เนื้อหาควรเคลื่อนที่ภายในมุมมองที่เลื่อนได้ทั่วไป การกลับด้านนี้เองที่ทำให้ scrollableArea
ดูเป็นธรรมชาติมากขึ้นเมื่อใช้คอนเทนเนอร์ที่เลื่อนได้มาตรฐาน
ตารางต่อไปนี้สรุปเครื่องหมายเดลต้าสำหรับสถานการณ์ที่พบบ่อย
ท่าทางของผู้ใช้ |
เดลต้าที่รายงานต่อ |
delta รายงานต่อ |
|---|---|---|
ตัวชี้เลื่อนขึ้น |
เชิงลบ |
เชิงบวก |
ตัวชี้เลื่อนลง |
เชิงบวก |
เชิงลบ |
ตัวชี้เลื่อนไปทางซ้าย |
เชิงลบ |
บวก (ลบสำหรับ RTL) |
ตัวชี้เลื่อนไปทางขวา |
เชิงบวก |
เชิงลบ (เชิงบวกสำหรับ RTL) |
(*) หมายเหตุเกี่ยวกับscrollableAreaเครื่องหมายเดลต้า: เครื่องหมายของเดลต้าจาก
scrollableAreaไม่ใช่การกลับค่าอย่างง่าย โดยจะพิจารณาอย่างชาญฉลาดในเรื่องต่อไปนี้
- การวางแนว: แนวตั้งหรือแนวนอน
LayoutDirection: LTR หรือ RTL (สำคัญอย่างยิ่งสำหรับการเลื่อนแนวนอน)reverseScrollingflag: เลือกว่าจะกลับด้านทิศทางการเลื่อนหรือไม่
นอกจากการกลับค่าเดลต้าการเลื่อนแล้ว scrollableArea ยังตัดเนื้อหา
ให้พอดีกับขอบเขตของเลย์เอาต์และจัดการการแสดงผลเอฟเฟกต์การเลื่อนเกิน
ด้วย โดยค่าเริ่มต้น ฟังก์ชันนี้จะใช้เอฟเฟกต์ที่ LocalOverscrollFactory มีให้
คุณปรับแต่งหรือปิดใช้ได้โดยใช้การโอเวอร์โหลด scrollableArea
ที่ยอมรับพารามิเตอร์ OverscrollEffect
กรณีที่ควรใช้ตัวแก้ไข scrollableArea
คุณควรใช้ตัวแก้ไข scrollableArea เมื่อต้องการสร้างคอมโพเนนต์การเลื่อนแบบกำหนดเองที่ตัวแก้ไข horizontalScroll หรือ verticalScroll หรือเลย์เอาต์แบบ Lazy ไม่ได้ให้บริการอย่างเพียงพอ ซึ่งมักจะเกี่ยวข้องกับกรณีต่อไปนี้
- ตรรกะเลย์เอาต์ที่กำหนดเอง: เมื่อการจัดเรียงรายการเปลี่ยนแปลงแบบไดนามิก ตามตำแหน่งการเลื่อน
- เอฟเฟกต์ภาพที่ไม่ซ้ำกัน: การใช้การเปลี่ยนรูป การปรับขนาด หรือเอฟเฟกต์อื่นๆ กับเด็กขณะเลื่อน
- การควบคุมโดยตรง: ต้องการการควบคุมกลไกการเลื่อนอย่างละเอียด
นอกเหนือจากที่
verticalScrollหรือเลย์เอาต์แบบเลซี่แสดง
สร้างรายการที่กำหนดเองคล้ายวงล้อโดยใช้ scrollableArea
ตัวอย่างต่อไปนี้แสดงการใช้ scrollableArea เพื่อสร้างรายการแนวตั้งที่กำหนดเอง ซึ่งรายการจะเล็กลงเมื่อเคลื่อนที่ออกจากกึ่งกลาง ทำให้เกิดเอฟเฟกต์ภาพคล้าย "วงล้อ" การเปลี่ยนรูปแบบที่ขึ้นอยู่กับการเลื่อนประเภทนี้เป็น
กรณีการใช้งานที่เหมาะสําหรับ scrollableArea
scrollableArea
@Composable private fun ScrollableAreaSample() { // ... Layout( modifier = Modifier .size(150.dp) .scrollableArea(scrollState, Orientation.Vertical) .background(Color.LightGray), // ... ) { measurables, constraints -> // ... // Update the maximum scroll value to not scroll beyond limits and stop when scroll // reaches the end. scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0) // Position the children within the layout. layout(constraints.maxWidth, viewportHeight) { // The current vertical scroll position, in pixels. val scrollY = scrollState.value val viewportCenterY = scrollY + viewportHeight / 2 var placeableLayoutPositionY = 0 placeables.forEach { placeable -> // This sample applies a scaling effect to items based on their distance // from the center, creating a wheel-like effect. // ... // Place the item horizontally centered with a layer transformation for // scaling to achieve wheel-like effect. placeable.placeRelativeWithLayer( x = constraints.maxWidth / 2 - placeable.width / 2, // Offset y by the scroll position to make placeable visible in the viewport. y = placeableLayoutPositionY - scrollY, ) { scaleX = scaleFactor scaleY = scaleFactor } // Move to the next item's vertical position. placeableLayoutPositionY += placeable.height } } } } // ...
ตัวแก้ไขที่เลื่อนได้
ตัวปรับแต่ง
scrollable
แตกต่างจากตัวปรับแต่งการเลื่อนตรงที่ scrollableตรวจหา
ท่าทางการเลื่อนและบันทึกเดลต้า แต่จะไม่ชดเชยเนื้อหาโดยอัตโนมัติ
แต่จะมอบสิทธิ์ให้ผู้ใช้ผ่าน
ScrollableState
ซึ่งจำเป็นต่อการทำงานของตัวแก้ไขนี้อย่างถูกต้อง
เมื่อสร้าง ScrollableState คุณต้องระบุฟังก์ชัน consumeScrollDelta
ซึ่งจะเรียกใช้ในแต่ละขั้นตอนการเลื่อน (โดยการป้อนข้อมูลท่าทางสัมผัส การเลื่อนแบบสมูท
หรือการปัด) พร้อมกับเดลต้าในหน่วยพิกเซล ฟังก์ชันนี้ต้องแสดงผล
ระยะทางการเลื่อนที่ใช้ไป เพื่อให้มั่นใจว่าระบบจะส่งต่อเหตุการณ์อย่างถูกต้อง
ในกรณีที่มีองค์ประกอบที่ซ้อนกันซึ่งมีตัวแก้ไข scrollable
ข้อมูลโค้ดต่อไปนี้จะตรวจหาท่าทางสัมผัสและแสดงค่าตัวเลขสำหรับออฟเซ็ต แต่จะไม่ชดเชยองค์ประกอบใดๆ
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(0f) } Box( Modifier .size(150.dp) .scrollable( orientation = Orientation.Vertical, // Scrollable state: describes how to consume // scrolling delta and update offset state = rememberScrollableState { delta -> offset += delta delta } ) .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(offset.toString()) } }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ทำความเข้าใจท่าทางสัมผัส
- ย้ายข้อมูล
CoordinatorLayoutไปยัง Compose - การใช้มุมมองใน Compose