หากต้องการปรับแต่งวิธีการทำงานของภาพเคลื่อนไหวการเปลี่ยนองค์ประกอบที่แชร์ คุณสามารถใช้พารามิเตอร์ 2-3 รายการเพื่อเปลี่ยนวิธีการทำงานขององค์ประกอบที่แชร์
ข้อกำหนดเฉพาะสำหรับภาพเคลื่อนไหว
หากต้องการเปลี่ยนข้อกำหนดของภาพเคลื่อนไหวที่ใช้สำหรับการเคลื่อนไหวของขนาดและตำแหน่ง ให้ระบุพารามิเตอร์ boundsTransform
อื่นใน Modifier.sharedElement()
ซึ่งจะเป็นตําแหน่ง Rect
เริ่มต้นและตําแหน่ง Rect
เป้าหมาย
เช่น หากต้องการให้ข้อความในตัวอย่างก่อนหน้านี้เคลื่อนไหวเป็นเส้นโค้ง ให้ระบุพารามิเตอร์ boundsTransform
เพื่อใช้ข้อกำหนด keyframes
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
คุณใช้ AnimationSpec
ใดก็ได้ ตัวอย่างนี้ใช้ข้อกําหนดของ keyframes
โหมดปรับขนาด
เมื่อสร้างภาพเคลื่อนไหวระหว่างขอบเขตที่แชร์ 2 รายการ คุณสามารถตั้งค่าพารามิเตอร์ resizeMode
เป็น RemeasureToBounds
หรือ ScaleToBounds
พารามิเตอร์นี้จะกำหนดลักษณะการเปลี่ยนองค์ประกอบที่แชร์ระหว่าง 2 สถานะ ScaleToBounds
แรก measured the child layout with the lookahead (or target) constraints. จากนั้นระบบจะปรับขนาดเลย์เอาต์ที่เสถียรของรายการย่อยให้พอดีกับขอบเขตที่แชร์
ScaleToBounds
เปรียบเสมือน "มาตราส่วนกราฟิก" ระหว่างรัฐต่างๆ
ส่วน RemeasureToBounds
จะวัดและจัดเรียงเลย์เอาต์ย่อยของ sharedBounds
ใหม่อีกครั้งด้วยข้อจำกัดแบบคงที่ที่เคลื่อนไหวตามขนาดเป้าหมาย การวัดผลอีกครั้งจะทริกเกอร์โดยการเปลี่ยนแปลงขนาดขอบเขต ซึ่งอาจเกิดขึ้นทุกเฟรม
สำหรับคอมโพสิเบิล Text
เราขอแนะนำให้ใช้ ScaleToBounds
เนื่องจากจะหลีกเลี่ยงการจัดเรียงใหม่และการจัดเรียงข้อความใหม่ในบรรทัดต่างๆ สำหรับขอบเขตที่มีสัดส่วนการแสดงผลต่างกัน และหากต้องการให้องค์ประกอบที่แชร์ 2 รายการต่อเนื่องกันแบบราบรื่น เราขอแนะนำให้ใช้ RemeasureToBounds
ความแตกต่างระหว่างโหมดปรับขนาด 2 โหมดนี้แสดงอยู่ในตัวอย่างต่อไปนี้
|
|
---|---|
ข้ามไปยังเลย์เอาต์สุดท้าย
โดยค่าเริ่มต้น เมื่อเปลี่ยนระหว่างเลย์เอาต์ 2 รูปแบบ ขนาดเลย์เอาต์จะเคลื่อนไหวระหว่างสถานะเริ่มต้นและสถานะสุดท้าย ลักษณะการทำงานนี้อาจไม่พึงประสงค์เมื่อสร้างภาพเคลื่อนไหวของเนื้อหา เช่น ข้อความ
ตัวอย่างต่อไปนี้แสดงข้อความอธิบาย "Lorem Ipsum" ที่ปรากฏบนหน้าจอ 2 วิธี ตัวอย่างแรก ข้อความจะจัดเรียงใหม่เมื่อเข้าสู่คอนเทนเนอร์ที่ขยายขนาดขึ้น ส่วนตัวอย่างที่ 2 ข้อความจะไม่จัดเรียงใหม่เมื่อขยายขนาด การเพิ่ม Modifier.skipToLookaheadSize()
จะช่วยป้องกันการจัดเรียงใหม่เมื่อข้อความมีความยาวมากขึ้น
ไม่มี Modifier.skipToLookahead() - สังเกตการเรียงบรรทัดข้อความ "Lorem Ipsum" ใหม่ |
Modifier.skipToLookahead() - สังเกตว่าข้อความ "Lorem Ipsum" ยังคงอยู่ในสถานะสุดท้ายที่จุดเริ่มต้นของภาพเคลื่อนไหว |
---|---|
คลิปและการซ้อนทับ
แนวคิดสําคัญในการสร้างองค์ประกอบที่แชร์ใน Compose คือการเรนเดอร์คอมโพสิเบิลจะยกระดับเป็นเลเยอร์วางซ้อนเมื่อเริ่มการเปลี่ยนเพื่อจับคู่กับคอมโพสิเบิลปลายทาง เพื่อให้คอมโพสิเบิลต่างๆ แชร์องค์ประกอบได้ ผลที่ได้คือ องค์ประกอบจะหนีขอบเขตขององค์ประกอบหลักและการเปลี่ยนรูปแบบเลเยอร์ (เช่น อัลฟาและมาตราส่วน)
องค์ประกอบจะแสดงผลบนองค์ประกอบ UI อื่นๆ ที่ไม่ได้แชร์ เมื่อการเปลี่ยนภาพเสร็จสิ้นแล้ว ระบบจะวางองค์ประกอบจากการวางซ้อนไปยัง DrawScope
ขององค์ประกอบนั้น
หากต้องการตัดองค์ประกอบที่แชร์เป็นรูปทรง ให้ใช้ฟังก์ชัน Modifier.clip()
แบบมาตรฐาน วางไว้หลัง sharedElement()
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
หากต้องการให้องค์ประกอบที่แชร์ไม่แสดงผลนอกคอนเทนเนอร์หลัก ให้ตั้งค่า clipInOverlayDuringTransition
ใน sharedElement()
โดยค่าเริ่มต้น clipInOverlayDuringTransition
จะใช้เส้นทางคลิปจาก sharedBounds()
หลักสำหรับขอบเขตที่แชร์แบบซ้อนกัน
หากต้องการรองรับการแสดงองค์ประกอบ UI ที่เฉพาะเจาะจง เช่น แถบด้านล่างหรือปุ่มการดำเนินการแบบลอยอยู่ ไว้ที่ด้านบนเสมอในระหว่างการเปลี่ยนองค์ประกอบที่แชร์ ให้ใช้ Modifier.renderInSharedTransitionScopeOverlay()
โดยค่าเริ่มต้น ตัวแก้ไขนี้จะเก็บเนื้อหาไว้ในการวางซ้อนในช่วงเวลาที่การเปลี่ยนหน้าที่ใช้ร่วมกันทำงานอยู่
ตัวอย่างเช่น ใน Jetsnack BottomAppBar
ต้องวางไว้ด้านบนขององค์ประกอบที่แชร์จนกว่าหน้าจอจะมองไม่เห็น การเพิ่มตัวแก้ไขลงในคอมโพสิเบิลจะยกระดับคอมโพสิเบิลนั้น
ไม่มี |
ด้วย |
---|---|
บางครั้งคุณอาจต้องการให้คอมโพสิชันที่ไม่ใช่คอมโพสิชันที่แชร์แสดงภาพเคลื่อนไหวและยังคงอยู่ด้านบนของคอมโพสิชันอื่นๆ ก่อนการเปลี่ยน ในกรณีเช่นนี้ ให้ใช้ renderInSharedTransitionScopeOverlay().animateEnterExit()
เพื่อแสดงภาพเคลื่อนไหวของคอมโพสิเบิลออกขณะที่ทรานซิชันองค์ประกอบที่แชร์ทำงานอยู่
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
ในกรณีที่ไม่บ่อยนักที่คุณต้องการไม่ให้องค์ประกอบที่แชร์แสดงผลในการวางซ้อน คุณสามารถตั้งค่า renderInOverlayDuringTransition
ใน sharedElement()
เป็น false ได้
แจ้งเลย์เอาต์แบบพี่น้องเกี่ยวกับการเปลี่ยนแปลงขนาดองค์ประกอบที่แชร์
โดยค่าเริ่มต้น sharedBounds()
และ sharedElement()
จะไม่แจ้งให้คอนเทนเนอร์หลักทราบถึงการเปลี่ยนแปลงขนาดเมื่อเลย์เอาต์เปลี่ยน
หากต้องการเผยแพร่การเปลี่ยนแปลงขนาดไปยังคอนเทนเนอร์หลักขณะที่เปลี่ยน ให้เปลี่ยนพารามิเตอร์ placeHolderSize
เป็น PlaceHolderSize.animatedSize
ซึ่งจะทำให้รายการขยายหรือหด รายการอื่นๆ ทั้งหมดในเลย์เอาต์จะตอบสนองต่อการเปลี่ยนแปลง
|
(สังเกตว่ารายการอื่นๆ ในรายการเลื่อนลงอย่างไรเมื่อรายการหนึ่งเติบโตขึ้น) |
---|---|