เพื่อปรับปรุงประสิทธิภาพองค์ประกอบของคอมโพเนนต์แบบอินเทอร์แอกทีฟที่ใช้
Modifier.clickable
เราได้เปิดตัว API ใหม่ API เหล่านี้ทำให้
การติดตั้งใช้งาน Indication
เช่น Ripples ที่มีประสิทธิภาพ
androidx.compose.foundation:foundation:1.7.0+
และ
androidx.compose.material:material-ripple:1.7.0+
มี API ต่อไปนี้
การเปลี่ยนแปลง:
เลิกใช้งานแล้ว |
การแทนที่ |
---|---|
|
|
|
มี API ใหม่ของ หมายเหตุ: ในบริบทนี้ "ไลบรารีสื่อการเรียนการสอน" หมายถึง |
|
ดังนี้
|
หน้านี้อธิบายผลกระทบจากการเปลี่ยนแปลงลักษณะการทำงานและคำแนะนำในการย้ายข้อมูลไปยัง API ใหม่
การเปลี่ยนแปลงลักษณะการทำงาน
เวอร์ชันไลบรารีต่อไปนี้มีการเปลี่ยนแปลงลักษณะการทำงานแบบระลอกคลื่น:
androidx.compose.material:material:1.7.0+
androidx.compose.material3:material3:1.3.0+
androidx.wear.compose:compose-material:1.4.0+
ไลบรารี Material เวอร์ชันเหล่านี้ไม่ได้ใช้ rememberRipple()
แล้ว แทน
พวกเขาใช้ Ripple API ใหม่ ดังนั้นจึงไม่ค้นหา LocalRippleTheme
ดังนั้นหากคุณตั้งค่า LocalRippleTheme
ในแอปพลิเคชัน Material
คอมโพเนนต์จะไม่ใช้ค่าเหล่านี้
หัวข้อต่อไปนี้จะอธิบายถึงวิธีเปลี่ยนกลับไปใช้ลักษณะการทำงานเดิมชั่วคราว
โดยไม่ต้องย้ายข้อมูล แต่เราขอแนะนำให้ย้ายข้อมูลไปยัง API ใหม่ สำหรับ
ดูวิธีการย้ายข้อมูลที่ย้ายข้อมูลจาก rememberRipple
ไปยัง ripple
และหัวข้อต่อๆ ไป
อัปเกรดเวอร์ชันไลบรารี Material โดยไม่ต้องย้ายข้อมูล
ในการเลิกบล็อกเวอร์ชันไลบรารีสำหรับการอัปเกรด คุณสามารถใช้
LocalUseFallbackRippleImplementation CompositionLocal
API ที่จะกำหนดค่า
คอมโพเนนต์วัสดุที่จะกลับไปใช้ลักษณะการทำงานเดิม
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
อย่าลืมใส่ข้อมูลนี้นอก MaterialTheme
เพื่อให้ Ripples เดิมสามารถ
จาก LocalIndication
ส่วนต่อไปนี้จะอธิบายวิธีย้ายข้อมูลไปยัง API ใหม่
ย้ายข้อมูลจาก rememberRipple
ไปยัง ripple
การใช้ไลบรารี Material
หากคุณใช้ไลบรารี Material ให้แทนที่ rememberRipple()
โดยตรงด้วย
การเรียกไปยัง ripple()
จากไลบรารีที่เกี่ยวข้อง API นี้สร้างระลอกคลื่น
โดยใช้ค่าที่ได้จาก API ธีม Material จากนั้นส่งคำสั่งซื้อที่ส่งคืน
ออบเจ็กต์ Modifier.clickable
และ/หรือคอมโพเนนต์อื่นๆ
ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ใช้ API ที่เลิกใช้งานแล้ว
Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple() ) ) { // ... }
คุณควรแก้ไขข้อมูลโค้ดด้านบนเป็น
@Composable private fun RippleExample() { Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = ripple() ) ) { // ... } }
โปรดทราบว่า ripple()
ไม่ใช่ฟังก์ชันที่ประกอบกันได้อีกต่อไปและไม่จำเป็นต้องเป็น
จำได้ นอกจากนี้ยังสามารถใช้ซ้ำได้ในหลายคอมโพเนนต์ คล้ายกับ
ตัวปรับแต่งด้วย ดังนั้นให้พิจารณาแยกการสร้างระลอกคลื่นออกเป็นค่าระดับบนสุดเพื่อ
บันทึกการจัดสรร
การใช้ระบบการออกแบบที่กำหนดเอง
หากคุณติดตั้งระบบออกแบบของคุณเอง โดยก่อนหน้านี้คุณใช้
rememberRipple()
พร้อมด้วย RippleTheme
ที่กำหนดเองเพื่อกำหนดค่าคลื่น
คุณควรระบุ Ripple API ของคุณเองที่มอบสิทธิ์ให้กับโหนด Ripple แทน
API เปิดเผยใน material-ripple
จากนั้นคอมโพเนนต์สามารถใช้ระลอกคลื่นของคุณเองได้
ที่ใช้ค่าธีมของคุณโดยตรง สำหรับข้อมูลเพิ่มเติม โปรดดูที่ย้ายข้อมูล
จากRippleTheme
ย้ายข้อมูลจาก RippleTheme
เลือกไม่ใช้การเปลี่ยนแปลงลักษณะการทำงานชั่วคราว
ไลบรารีเนื้อหามี CompositionLocal
ชั่วคราว
LocalUseFallbackRippleImplementation
ซึ่งใช้เพื่อกำหนดค่าทั้งหมด
คอมโพเนนต์วัสดุที่จะกลับไปใช้ rememberRipple
ด้วยวิธีนี้
rememberRipple
ยังคงค้นหา LocalRippleTheme
ต่อไป
ข้อมูลโค้ดต่อไปนี้สาธิตวิธีใช้
API ของ LocalUseFallbackRippleImplementation CompositionLocal
:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
หากคุณใช้ธีมแอปที่กำหนดเองซึ่งสร้างขึ้นจาก Material ให้ทำดังนี้ ใส่องค์ประกอบไว้ภายในธีมของแอปอย่างปลอดภัย:
@OptIn(ExperimentalMaterialApi::class) @Composable fun MyAppTheme(content: @Composable () -> Unit) { CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme(content = content) } }
โปรดดูข้อมูลเพิ่มเติมที่หัวข้ออัปเกรดเวอร์ชันไลบรารี Material โดยไม่มี การย้ายข้อมูล
ใช้ RippleTheme
เพื่อปิดใช้ระลอกคลื่นของคอมโพเนนต์ที่กำหนด
ไลบรารี material
และ material3
แสดง RippleConfiguration
และ
LocalRippleConfiguration
ซึ่งช่วยให้คุณกำหนดค่าลักษณะที่ปรากฏของ
ระลอกคลื่นภายในต้นไม้ย่อย โปรดทราบว่า RippleConfiguration
และ
LocalRippleConfiguration
เป็นเวอร์ชันทดลองและมีไว้สำหรับ 1 คอมโพเนนต์เท่านั้น
การปรับแต่งได้มากขึ้น การกำหนดค่าส่วนกลาง/ทั้งธีมยังไม่รองรับรายการต่อไปนี้
API; ดูการใช้ RippleTheme
เพื่อเปลี่ยนแปลง Ripples ทั้งหมดทั่วโลกใน
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับกรณีการใช้งานดังกล่าว
ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ใช้ API ที่เลิกใช้งานแล้ว
private object DisabledRippleTheme : RippleTheme { @Composable override fun defaultColor(): Color = Color.Transparent @Composable override fun rippleAlpha(): RippleAlpha = RippleAlpha(0f, 0f, 0f, 0f) } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleTheme) { Button { // ... } }
คุณควรแก้ไขข้อมูลโค้ดด้านบนเป็น
CompositionLocalProvider(LocalRippleConfiguration provides null) { Button { // ... } }
ใช้ RippleTheme
เพื่อเปลี่ยนสี/อัลฟ่าของระลอกคลื่นสำหรับคอมโพเนนต์ที่กำหนด
ตามที่อธิบายไว้ในส่วนก่อนหน้านี้ RippleConfiguration
และ
LocalRippleConfiguration
เป็น API ทดลองและมีไว้สำหรับ
การปรับแต่งต่อคอมโพเนนต์
ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ใช้ API ที่เลิกใช้งานแล้ว
private object DisabledRippleThemeColorAndAlpha : RippleTheme { @Composable override fun defaultColor(): Color = Color.Red @Composable override fun rippleAlpha(): RippleAlpha = MyRippleAlpha } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleThemeColorAndAlpha) { Button { // ... } }
คุณควรแก้ไขข้อมูลโค้ดด้านบนเป็น
@OptIn(ExperimentalMaterialApi::class) private val MyRippleConfiguration = RippleConfiguration(color = Color.Red, rippleAlpha = MyRippleAlpha) // ... CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) { Button { // ... } }
ใช้ RippleTheme
เพื่อเปลี่ยนแปลง Ripples ทั้งหมดในแอปพลิเคชัน
ก่อนหน้านี้ คุณสามารถใช้ LocalRippleTheme
เพื่อกำหนดลักษณะระลอกคลื่นที่
ในระดับธีมทั้งหมด โดยเป็นจุดผสานรวมระหว่างโซลูชัน
องค์ประกอบของระบบการออกแบบ
ในพื้นที่และระลอกคลื่น แทนที่จะแสดงโฆษณาทั่วไป
ธีมพื้นฐาน material-ripple
จะแสดง createRippleModifierNode()
ฟังก์ชันนี้ช่วยให้ไลบรารีระบบการออกแบบสร้าง
ติดตั้งใช้งาน wrapper
ที่ค้นหาค่าธีมแล้วมอบสิทธิ์
การติดตั้งใช้งานระลอกคลื่นไปยังโหนดที่สร้างโดยฟังก์ชันนี้
ซึ่งจะช่วยให้ระบบการออกแบบสามารถค้นหาสิ่งที่ต้องการได้โดยตรง และแสดงข้อมูล
ต้องมีเลเยอร์ธีมที่ผู้ใช้กำหนดค่าได้ที่ด้านบนโดยที่ไม่สอดคล้องกับ
มีอะไรบ้างที่เลเยอร์ material-ripple
การเปลี่ยนแปลงนี้ยังทำให้
ระบุอย่างชัดเจนถึงธีม/ข้อมูลจำเพาะที่ระลอกคลื่นนั้นสอดคล้อง เนื่องจากเป็น
ripple API เองที่กำหนดสัญญานั้นๆ มากกว่าที่จะกำหนดโดยนัย
ที่มาจากธีม
ดูคำแนะนำได้ที่การใช้งาน Ripple API ใน Material ไลบรารี และแทนที่การเรียกไปยังคนท้องถิ่นในการจัดองค์ประกอบเนื้อหาตามที่จำเป็นสำหรับ ระบบการออกแบบของคุณเอง
ย้ายข้อมูลจาก Indication
ไปยัง IndicationNodeFactory
ขับผ่าน Indication
หากคุณเพียงแค่สร้าง Indication
เพื่อส่งต่อ เช่น สร้าง
ระลอกคลื่นเพื่อส่งไปยัง Modifier.clickable
หรือ Modifier.indication
คุณไม่ต้อง
ต้องทำการเปลี่ยนแปลงอะไร IndicationNodeFactory
รับค่าจาก Indication
เพื่อให้ทุกอย่างคอมไพล์และทำงานได้ต่อไป
กำลังสร้าง Indication
หากคุณสร้างการใช้งาน Indication
ของคุณเอง การย้ายข้อมูลควร
เรียบง่ายในกรณีส่วนใหญ่ ตัวอย่างเช่น ลองพิจารณา Indication
ที่ใช้พารามิเตอร์
ปรับผลเมื่อกด:
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } } private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
คุณย้ายข้อมูลได้ใน 2 ขั้นตอน
ย้ายข้อมูล
ScaleIndicationInstance
เป็นDrawModifierNode
แพลตฟอร์ม API สำหรับDrawModifierNode
คล้ายกับIndicationInstance
มาก โดยจะแสดงContentDrawScope#draw()
ที่มีฟังก์ชันการทำงานเทียบเท่ากับIndicationInstance#drawContent()
คุณต้องเปลี่ยนฟังก์ชันนั้น จากนั้น ใช้ตรรกะcollectLatest
ภายในโหนดโดยตรง แทนฟังก์ชันIndication
ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ใช้ API ที่เลิกใช้งานแล้ว
private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
คุณควรแก้ไขข้อมูลโค้ดด้านบนเป็น
private class ScaleIndicationNode( private val interactionSource: InteractionSource ) : Modifier.Node(), DrawModifierNode { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) private suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } private suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun onAttach() { coroutineScope.launch { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> animateToPressed(interaction.pressPosition) is PressInteraction.Release -> animateToResting() is PressInteraction.Cancel -> animateToResting() } } } } override fun ContentDrawScope.draw() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@draw.drawContent() } } }
ย้ายข้อมูล
ScaleIndication
เพื่อใช้IndicationNodeFactory
เนื่องจาก ตรรกะของคอลเลกชันถูกย้ายไปอยู่ในโหนด เป็นโรงงานที่ง่ายมาก ซึ่งเป็นสิ่งที่มีหน้าที่เดียวคือการสร้างอินสแตนซ์โหนดตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้ใช้ API ที่เลิกใช้งานแล้ว
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } }
คุณควรแก้ไขข้อมูลโค้ดด้านบนเป็น
object ScaleIndicationNodeFactory : IndicationNodeFactory { override fun create(interactionSource: InteractionSource): DelegatableNode { return ScaleIndicationNode(interactionSource) } override fun hashCode(): Int = -1 override fun equals(other: Any?) = other === this }
กำลังใช้ Indication
เพื่อสร้าง IndicationInstance
ในกรณีส่วนใหญ่ คุณควรใช้ Modifier.indication
เพื่อแสดง Indication
สำหรับ
คอมโพเนนต์ อย่างไรก็ตาม ในบางกรณีที่เกิดขึ้นไม่บ่อยนัก คุณจะต้องสร้าง
IndicationInstance
ที่ใช้ rememberUpdatedInstance
คุณต้องอัปเดต
เพื่อตรวจสอบว่า Indication
เป็น IndicationNodeFactory
หรือไม่ เพื่อให้คุณ
สามารถใช้การติดตั้งที่น้อยกว่า ตัวอย่างเช่น Modifier.indication
จะ
มอบสิทธิ์ภายในให้กับโหนดที่สร้างขึ้นหากเป็น IndicationNodeFactory
ถ้า
ไม่ใช่ แต่จะใช้ Modifier.composed
เพื่อโทรหา rememberUpdatedInstance