สร้างภาพเคลื่อนไหวการเปลี่ยนแปลงการออกแบบโดยใช้การเปลี่ยน

ลองใช้วิธีเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนำสำหรับ Android ดูวิธีใช้ภาพเคลื่อนไหวใน Compose

เฟรมเวิร์กการเปลี่ยนรูปแบบของ Android ช่วยให้คุณสร้างภาพเคลื่อนไหวทุกประเภทใน UI ได้โดยระบุเลย์เอาต์เริ่มต้นและเลย์เอาต์สิ้นสุด คุณสามารถเลือกประเภทภาพเคลื่อนไหวที่ต้องการ เช่น การแสดงหรือซ่อนมุมมองแบบค่อยๆ ปรากฏหรือค่อยๆ หายไป หรือเปลี่ยนขนาดมุมมอง และเฟรมเวิร์กการเปลี่ยนจะกำหนดวิธีแสดงภาพเคลื่อนไหวจากเลย์เอาต์เริ่มต้นไปยังเลย์เอาต์สุดท้าย

เฟรมเวิร์กการเปลี่ยนผ่านมีฟีเจอร์ต่อไปนี้

  • ภาพเคลื่อนไหวระดับกลุ่ม: ใช้เอฟเฟกต์ภาพเคลื่อนไหวกับมุมมองทั้งหมดในลําดับชั้นของมุมมอง
  • ภาพเคลื่อนไหวในตัว: ใช้ภาพเคลื่อนไหวที่กำหนดไว้ล่วงหน้าสำหรับเอฟเฟกต์ทั่วไป เช่น การจางออกหรือการเคลื่อนไหว
  • การรองรับไฟล์ทรัพยากร: โหลดลำดับชั้นการแสดงผลและภาพเคลื่อนไหวในตัวจากไฟล์ทรัพยากรของเลย์เอาต์
  • Lifecycle Callback: รับ Callback ที่ควบคุมกระบวนการเปลี่ยนแปลงลำดับชั้นและภาพเคลื่อนไหว

ดูโค้ดตัวอย่างที่แสดงภาพเคลื่อนไหวระหว่างการเปลี่ยนแปลงเลย์เอาต์ได้ที่ BasicTransition

ขั้นตอนพื้นฐานในการสร้างภาพเคลื่อนไหวระหว่างเลย์เอาต์ 2 รูปแบบมีดังนี้

  1. สร้างออบเจ็กต์ Scene สำหรับเลย์เอาต์เริ่มต้นและสิ้นสุด อย่างไรก็ตาม ฉากของเลย์เอาต์เริ่มต้นมักกำหนดโดยอัตโนมัติจากเลย์เอาต์ปัจจุบัน
  2. สร้างออบเจ็กต์ Transition เพื่อกำหนดประเภทภาพเคลื่อนไหวที่ต้องการ
  3. เรียกใช้ TransitionManager.go() จากนั้นระบบจะเรียกใช้ภาพเคลื่อนไหวเพื่อสลับเลย์เอาต์

แผนภาพในรูปที่ 1 แสดงความสัมพันธ์ระหว่างเลย์เอาต์ ฉาก การเปลี่ยนภาพ และภาพเคลื่อนไหวขั้นสุดท้าย

รูปที่ 1 ภาพพื้นฐานที่แสดงวิธีที่เฟรมเวิร์กการเปลี่ยนสร้างภาพเคลื่อนไหว

สร้างฉาก

ฉากจะจัดเก็บสถานะของลําดับชั้นมุมมอง ซึ่งรวมถึงมุมมองทั้งหมดและค่าพร็อพเพอร์ตี้ของมุมมอง เฟรมเวิร์กการเปลี่ยนสามารถเรียกใช้ภาพเคลื่อนไหวระหว่าง ฉากเริ่มต้นกับฉากจบได้

คุณสร้างฉากได้จากไฟล์ทรัพยากรเลย์เอาต์หรือจากกลุ่มมุมมองในโค้ด อย่างไรก็ตาม ฉากเริ่มต้นของการเปลี่ยนฉากมักจะกำหนดโดยอัตโนมัติจาก UI ปัจจุบัน

ฉากยังกำหนดการดำเนินการของตนเองที่จะทำงานเมื่อคุณเปลี่ยนฉากได้ด้วย ฟีเจอร์นี้มีประโยชน์ในการล้างการตั้งค่ามุมมองหลังจากที่คุณเปลี่ยนไปใช้ฉากอื่น

สร้างฉากจากทรัพยากรเลย์เอาต์

คุณสามารถสร้างอินสแตนซ์ Scene จากไฟล์ทรัพยากรเลย์เอาต์ได้โดยตรง ใช้เทคนิคนี้เมื่อลําดับชั้นของมุมมองในไฟล์เป็นแบบคงที่ส่วนใหญ่ ฉากที่ได้แสดงสถานะลําดับชั้นของมุมมอง ณ เวลาที่คุณสร้างอินสแตนซ์ Scene หากเปลี่ยนลําดับชั้นของมุมมอง ให้สร้างฉากขึ้นมาใหม่ เฟรมเวิร์กจะสร้างฉากจากลําดับชั้นมุมมองทั้งหมดในไฟล์ คุณสร้างฉากจากบางส่วนของไฟล์เลย์เอาต์ไม่ได้

หากต้องการสร้างอินสแตนซ์ Scene จากไฟล์ทรัพยากรเลย์เอาต์ ให้ดึงข้อมูลรูทของฉากจากเลย์เอาต์เป็น ViewGroup จากนั้นเรียกใช้ฟังก์ชัน Scene.getSceneForLayout() ด้วยรูทฉากและรหัสแหล่งข้อมูลของไฟล์เลย์เอาต์ที่มีลําดับชั้นของมุมมองสําหรับฉาก

กำหนดเลย์เอาต์สำหรับฉาก

ข้อมูลโค้ดในส่วนที่เหลือของส่วนนี้จะแสดงวิธีสร้างฉาก 2 ฉากที่มีองค์ประกอบรูทฉากเดียวกัน นอกจากนี้ ตัวอย่างข้อมูลยังแสดงให้เห็นว่าคุณโหลดออบเจ็กต์ Scene ที่ไม่เกี่ยวข้องหลายรายการได้โดยไม่ต้องบอกเป็นนัยว่าออบเจ็กต์เหล่านั้นเกี่ยวข้องกัน

ตัวอย่างนี้ประกอบด้วยการกำหนดเลย์เอาต์ต่อไปนี้

  • เลย์เอาต์หลักของกิจกรรมที่มีป้ายกำกับข้อความและกิจกรรมย่อย FrameLayout
  • ConstraintLayout สำหรับฉากแรกที่มีช่องข้อความ 2 ช่อง
  • ConstraintLayout สำหรับฉากที่ 2 ที่มีช่องข้อความ 2 ช่องเดียวกันในลำดับที่แตกต่างกัน

ตัวอย่างนี้ออกแบบมาเพื่อให้ภาพเคลื่อนไหวทั้งหมดเกิดขึ้นภายในเลย์เอาต์ย่อยของเลย์เอาต์หลักสำหรับกิจกรรม ป้ายกํากับข้อความในเลย์เอาต์หลักจะยังคงเป็นแบบคงที่

เลย์เอาต์หลักสําหรับกิจกรรมมีคำจำกัดความดังนี้

res/layout/activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/master_layout">
    <TextView
        android:id="@+id/title"
        ...
        android:text="Title"/>
    <FrameLayout
        android:id="@+id/scene_root">
        <include layout="@layout/a_scene" />
    </FrameLayout>
</LinearLayout>

คําจํากัดความเลย์เอาต์นี้มีช่องข้อความและ FrameLayout ย่อยสําหรับรูทฉาก เลย์เอาต์สำหรับฉากแรกจะรวมอยู่ในไฟล์เลย์เอาต์หลัก ซึ่งจะช่วยให้แอปแสดงไฟล์ดังกล่าวเป็นส่วนหนึ่งของอินเทอร์เฟซผู้ใช้เริ่มต้นและโหลดไฟล์ดังกล่าวลงในฉากได้ด้วย เนื่องจากเฟรมเวิร์กจะโหลดไฟล์เลย์เอาต์ทั้งไฟล์ลงในฉากได้เท่านั้น

เลย์เอาต์ของฉากแรกจะกำหนดดังนี้

res/layout/a_แพลตฟอร์ม.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    
</androidx.constraintlayout.widget.ConstraintLayout>

เลย์เอาต์ของฉากที่สองมีช่องข้อความ 2 ช่องเดียวกันซึ่งมีรหัสเดียวกัน แต่เรียงลำดับต่างกัน โดยมีคำจำกัดความดังนี้

res/layout/another_เสนอราคา.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    
</androidx.constraintlayout.widget.ConstraintLayout>

สร้างฉากจากเลย์เอาต์

หลังจากสร้างคําจํากัดความสําหรับเลย์เอาต์ข้อจํากัด 2 รายการแล้ว คุณจะได้รับฉากสําหรับแต่ละรายการ ซึ่งจะช่วยให้คุณเปลี่ยนไปมาระหว่างการกำหนดค่า UI ทั้ง 2 แบบได้ คุณต้องมีการอ้างอิงไปยังรูทของฉากและรหัสทรัพยากรของเลย์เอาต์เพื่อดูฉาก

ข้อมูลโค้ดต่อไปนี้แสดงวิธีรับการอ้างอิงถึงรูทของฉากและสร้างออบเจ็กต์ Scene 2 รายการจากไฟล์เลย์เอาต์

Kotlin

val sceneRoot: ViewGroup = findViewById(R.id.scene_root)
val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this)
val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)

Java

Scene aScene;
Scene anotherScene;

// Create the scene root for the scenes in this app.
sceneRoot = (ViewGroup) findViewById(R.id.scene_root);

// Create the scenes.
aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this);
anotherScene =
    Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);

ตอนนี้ในแอปจะมีออบเจ็กต์ Scene 2 รายการตามลําดับชั้นของมุมมอง ฉากทั้ง 2 ฉากใช้รูทฉากที่กําหนดโดยองค์ประกอบ FrameLayout ใน res/layout/activity_main.xml

สร้างฉากในโค้ด

นอกจากนี้ คุณยังสร้างอินสแตนซ์ Scene ในโค้ดจากออบเจ็กต์ ViewGroup ได้ด้วย ใช้เทคนิคนี้เมื่อคุณแก้ไขลําดับชั้นของมุมมองในโค้ดโดยตรงหรือเมื่อคุณสร้างลําดับชั้นแบบไดนามิก

หากต้องการสร้างฉากจากลําดับชั้นมุมมองในโค้ด ให้ใช้คอนสตรคเตอร์ Scene(sceneRoot, viewHierarchy) การเรียกคอนสตรคเตอร์นี้จะเทียบเท่ากับการเรียกใช้ฟังก์ชัน Scene.getSceneForLayout() เมื่อคุณขยายไฟล์เลย์เอาต์แล้ว

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างอินสแตนซ์ Scene จากองค์ประกอบรากของฉากและลำดับชั้นการดูสำหรับฉากในโค้ดของคุณ

Kotlin

val sceneRoot = someLayoutElement as ViewGroup
val viewHierarchy = someOtherLayoutElement as ViewGroup
val scene: Scene = Scene(sceneRoot, viewHierarchy)

Java

Scene mScene;

// Obtain the scene root element.
sceneRoot = (ViewGroup) someLayoutElement;

// Obtain the view hierarchy to add as a child of
// the scene root when this scene is entered.
viewHierarchy = (ViewGroup) someOtherLayoutElement;

// Create a scene.
mScene = new Scene(sceneRoot, mViewHierarchy);

สร้างการทำงานของฉาก

เฟรมเวิร์กนี้จะช่วยคุณระบุการทำงานของฉากที่กำหนดเองที่ระบบใช้เมื่อเข้าหรือออกจากฉาก ในหลายกรณี การกำหนดการดำเนินการของฉากที่กําหนดเองนั้นไม่จําเป็น เนื่องจากเฟรมเวิร์กจะแสดงภาพเคลื่อนไหวของการเปลี่ยนแปลงระหว่างฉากโดยอัตโนมัติ

การดำเนินการกับฉากมีประโยชน์ในการจัดการกับกรณีต่อไปนี้

  • วิธีทำให้มุมมองที่ไม่ใช่ในลําดับชั้นเดียวกันเคลื่อนไหว คุณทำให้มุมมองของฉากเริ่มต้นและฉากสุดท้ายเคลื่อนไหวได้โดยใช้การดำเนินการของฉากออกและฉากเข้า
  • หากต้องการสร้างภาพเคลื่อนไหวของมุมมองที่เฟรมเวิร์กทรานซิชันสร้างภาพเคลื่อนไหวโดยอัตโนมัติไม่ได้ เช่น วัตถุ ListView ดูข้อมูลเพิ่มเติมได้ที่ส่วนข้อจำกัด

หากต้องการระบุการดำเนินการของฉากที่กำหนดเอง ให้กำหนดการดำเนินการเป็นออบเจ็กต์ Runnable แล้วส่งไปยังฟังก์ชัน Scene.setExitAction() หรือ Scene.setEnterAction() เฟรมเวิร์กจะเรียกใช้ฟังก์ชัน setExitAction() ในฉากเริ่มต้นก่อนที่จะเรียกใช้ภาพเคลื่อนไหวในการเปลี่ยนฉาก และเรียกใช้ฟังก์ชัน setEnterAction() ในฉากสุดท้ายหลังจากเรียกใช้ภาพเคลื่อนไหวในการเปลี่ยนฉาก

ใช้ทรานซิชัน

เฟรมเวิร์กการเปลี่ยนจะแสดงรูปแบบของภาพเคลื่อนไหวระหว่างฉากด้วยออบเจ็กต์ Transition คุณสร้างตัวอย่าง Transition ได้โดยใช้คลาสย่อยในตัว เช่น AutoTransition และ Fade หรือกำหนดการเปลี่ยนของคุณเอง จากนั้นคุณจะเรียกใช้ภาพเคลื่อนไหวระหว่างฉากได้โดยส่ง Scene สุดท้ายและ Transition ไปยัง TransitionManager.go()

วงจรการเปลี่ยนมีลักษณะคล้ายกับวงจรของกิจกรรม และแสดงสถานะการเปลี่ยนที่เฟรมเวิร์กตรวจสอบระหว่างช่วงเริ่มต้นและช่วงสิ้นสุดของภาพเคลื่อนไหว เมื่ออยู่ในสถานะวงจรที่สำคัญ เฟรมเวิร์กจะเรียกใช้ฟังก์ชันการเรียกกลับที่คุณสามารถใช้เพื่อปรับอินเทอร์เฟซผู้ใช้ในขั้นตอนต่างๆ ของการเปลี่ยนผ่าน

สร้างทรานซิชัน

ส่วนก่อนหน้านี้แสดงวิธีสร้างฉากที่แสดงสถานะของลําดับชั้นมุมมองต่างๆ เมื่อกำหนดฉากเริ่มต้นและฉากสิ้นสุดที่ต้องการเปลี่ยนแล้ว ให้สร้างออบเจ็กต์ Transition ที่กำหนดภาพเคลื่อนไหว เฟรมเวิร์กนี้ให้คุณระบุการเปลี่ยนในตัวในไฟล์ทรัพยากรและเพิ่มพองในโค้ดหรือสร้างอินสแตนซ์การเปลี่ยนในตัวในโค้ดโดยตรง

ตารางที่ 1 ประเภทการเปลี่ยนที่มีอยู่แล้ว

ชั้น ติดแท็ก เอฟเฟ็กต์
AutoTransition <autoTransition/> การเปลี่ยนที่เป็นค่าเริ่มต้น จากนั้นค่อยๆ เลือนหายไป ย้ายและปรับขนาด และค่อยๆ เลือนหายไปในมุมมองต่างๆ ตามลำดับ
ChangeBounds <changeBounds/> ย้ายและปรับขนาดมุมมอง
ChangeClipBounds <changeClipBounds/> จับภาพView.getClipBounds()ก่อนและหลังฉากเปลี่ยนแปลง และแสดงการเปลี่ยนแปลงเหล่านั้นเป็นภาพเคลื่อนไหวระหว่างการเปลี่ยนฉาก
ChangeImageTransform <changeImageTransform/> จับภาพเมทริกซ์ของ ImageView ก่อนและหลังการเปลี่ยนแปลงฉาก และสร้างภาพเคลื่อนไหวระหว่างการเปลี่ยนฉาก
ChangeScroll <changeScroll/> บันทึกคุณสมบัติการเลื่อนของเป้าหมายก่อนและหลังการเปลี่ยนแปลงฉาก และแสดงภาพเคลื่อนไหวของการเปลี่ยนแปลง
ChangeTransform <changeTransform/> บันทึกขนาดและการหมุนของมุมมองก่อนและหลังเปลี่ยนฉาก และทำภาพเคลื่อนไหวของการเปลี่ยนแปลงเหล่านั้นระหว่างการเปลี่ยนฉาก
Explode <explode/> ติดตามการเปลี่ยนแปลงระดับการมองเห็นของมุมมองเป้าหมายในฉากเริ่มต้นและฉากสุดท้าย และย้ายมุมมองเข้าหรือออกจากขอบของฉาก
Fade <fade/> fade_in แสดงในมุมมองแบบเลื่อนลง
fade_out ยอดดูค่อยๆ หายไป
fade_in_out (ค่าเริ่มต้น) แสดง fade_out ตามด้วย fade_in
Slide <slide/> ติดตามการเปลี่ยนแปลงระดับการมองเห็นของมุมมองเป้าหมายในฉากเริ่มต้นและฉากสุดท้าย และเลื่อนมุมมองเข้าหรือออกจากขอบของฉาก

สร้างอินสแตนซ์การเปลี่ยนจากไฟล์ทรัพยากร

เทคนิคนี้ช่วยให้คุณแก้ไขคําจํากัดความของการเปลี่ยนโดยไม่เปลี่ยนโค้ดของกิจกรรม เทคนิคนี้ยังมีประโยชน์ในการแยกคำจำกัดความการเปลี่ยนที่ซับซ้อนออกจากโค้ดของแอปพลิเคชันด้วย ดังที่แสดงในส่วนเกี่ยวกับการระบุการเปลี่ยนหลายรายการ

หากต้องการระบุทรานซิชันในตัวในไฟล์ทรัพยากร ให้ทำตามขั้นตอนต่อไปนี้

  • เพิ่มไดเรกทอรี res/transition/ ลงในโปรเจ็กต์
  • สร้างไฟล์ทรัพยากร XML ใหม่ภายในไดเรกทอรีนี้
  • เพิ่มโหนด XML สำหรับการเปลี่ยนในตัวแบบใดแบบหนึ่ง

ตัวอย่างเช่น ไฟล์ทรัพยากรต่อไปนี้จะระบุทรานซิชัน Fade

res/transition/fade_transition.xml

<fade xmlns:android="http://schemas.android.com/apk/res/android" />

ข้อมูลโค้ดต่อไปนี้แสดงวิธีขยายอินสแตนซ์ Transition ภายในกิจกรรมจากไฟล์ทรัพยากร

Kotlin

var fadeTransition: Transition =
    TransitionInflater.from(this)
                      .inflateTransition(R.transition.fade_transition)

Java

Transition fadeTransition =
        TransitionInflater.from(this).
        inflateTransition(R.transition.fade_transition);

สร้างอินสแตนซ์การเปลี่ยนผ่านในโค้ดของคุณ

เทคนิคนี้มีประโยชน์ในการสร้างออบเจ็กต์ทรานซิชันแบบไดนามิกหากคุณแก้ไขอินเทอร์เฟซผู้ใช้ในโค้ด และสร้างอินสแตนซ์ทรานซิชันในตัวแบบง่ายที่มีพารามิเตอร์น้อยหรือไม่มีเลย

หากต้องการสร้างอินสแตนซ์ของทรานซิชันในตัว ให้เรียกใช้คอนสตรัคเตอร์แบบสาธารณะรายการใดรายการหนึ่งในคลาสย่อยของคลาส Transition ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้สร้างอินสแตนซ์ของทรานซิชัน Fade

Kotlin

var fadeTransition: Transition = Fade()

Java

Transition fadeTransition = new Fade();

ใช้ทรานซิชัน

โดยปกติแล้ว คุณจะใช้ทรานซิชันเพื่อเปลี่ยนระหว่างลําดับชั้นของมุมมองต่างๆ เพื่อตอบสนองต่อเหตุการณ์ เช่น การดําเนินการของผู้ใช้ ตัวอย่างเช่น ลองพิจารณาแอปการค้นหา เมื่อผู้ใช้ป้อนข้อความค้นหาและแตะปุ่มค้นหา แอปจะเปลี่ยนเป็นฉากที่แสดงเลย์เอาต์ผลการค้นหาในขณะที่ใช้การเปลี่ยนที่ทำให้ปุ่มค้นหาค่อยๆ จางลงและแสดงในผลการค้นหา

หากต้องการเปลี่ยนฉากขณะใช้ทรานซิชันเพื่อตอบสนองต่อเหตุการณ์ในกิจกรรม ให้เรียกใช้ฟังก์ชันคลาส TransitionManager.go() ที่มีฉากสิ้นสุดและอินสแตนซ์ทรานซิชันที่จะใช้สำหรับภาพเคลื่อนไหว ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

Kotlin

TransitionManager.go(endingScene, fadeTransition)

Java

TransitionManager.go(endingScene, fadeTransition);

เฟรมเวิร์กจะเปลี่ยนลําดับชั้นของมุมมองภายในรูทของฉากด้วยลําดับชั้นของมุมมองจากฉากสุดท้ายขณะเรียกใช้ภาพเคลื่อนไหวที่อินสแตนซ์การเปลี่ยนระบุ ฉากเริ่มต้นคือฉากสุดท้ายจากทรานซิชันล่าสุด หากไม่มีการเปลี่ยนก่อนหน้า ระบบจะกำหนดฉากเริ่มต้นโดยอัตโนมัติจากสถานะปัจจุบันของอินเทอร์เฟซผู้ใช้

หากคุณไม่ได้ระบุอินสแตนซ์การเปลี่ยน เครื่องมือจัดการการเปลี่ยนสามารถใช้การเปลี่ยนอัตโนมัติที่ทําสิ่งที่เหมาะสมสําหรับสถานการณ์ส่วนใหญ่ ดูข้อมูลเพิ่มเติมได้ที่ข้อมูลอ้างอิง API สำหรับคลาส TransitionManager

เลือกมุมมองเป้าหมายที่ต้องการ

เฟรมเวิร์กจะใช้ทรานซิชันกับมุมมองทั้งหมดในฉากเริ่มต้นและฉากสิ้นสุดโดยค่าเริ่มต้น ในบางกรณี คุณอาจต้องการใช้ภาพเคลื่อนไหวกับมุมมองชุดย่อยในฉากเท่านั้น เฟรมเวิร์กนี้ช่วยให้คุณเลือกมุมมองที่ต้องการทำให้เคลื่อนไหวได้ ตัวอย่างเช่น เฟรมเวิร์กไม่รองรับการแสดงภาพเคลื่อนไหวของการเปลี่ยนแปลงออบเจ็กต์ ListView ดังนั้นอย่าพยายามแสดงภาพเคลื่อนไหวระหว่างการเปลี่ยน

มุมมองแต่ละรายการที่แสดงภาพเคลื่อนไหวของทรานซิชันเรียกว่าเป้าหมาย คุณเลือกได้เฉพาะเป้าหมายที่เป็นส่วนหนึ่งของลำดับชั้นการดูที่เชื่อมโยงกับฉากเท่านั้น

หากต้องการนํามุมมองอย่างน้อย 1 รายการออกจากรายการเป้าหมาย ให้เรียกใช้เมธอด removeTarget() ก่อนเริ่มการเปลี่ยน หากต้องการเพิ่มเฉพาะมุมมองที่คุณระบุลงในรายการเป้าหมาย ให้เรียกใช้ฟังก์ชัน addTarget() ดูข้อมูลเพิ่มเติมได้ที่การอ้างอิง API สําหรับคลาส Transition

ระบุทรานซิชันหลายรายการ

หากต้องการให้ภาพเคลื่อนไหวมีประสิทธิภาพสูงสุด ให้จับคู่กับประเภทการเปลี่ยนแปลงที่เกิดขึ้นระหว่างฉาก เช่น หากคุณนำมุมมองบางรายการออกและเพิ่มมุมมองอื่นๆ ระหว่างฉาก ภาพเคลื่อนไหวที่ค่อยๆ เลือนออกหรือค่อยๆ เลือนเข้าจะเป็นตัวบ่งชี้ที่เห็นได้ชัดว่ามุมมองบางรายการไม่พร้อมใช้งานแล้ว หากคุณย้ายมุมมองไปยังจุดต่างๆ บนหน้าจอ คุณควรทำให้การเคลื่อนไหวเป็นแบบภาพเคลื่อนไหวเพื่อให้ผู้ใช้สังเกตเห็นตำแหน่งใหม่ของมุมมอง

คุณไม่จำเป็นต้องเลือกภาพเคลื่อนไหวเพียงรายการเดียว เนื่องจากเฟรมเวิร์กทรานซิชันช่วยให้คุณรวมเอฟเฟกต์ภาพเคลื่อนไหวในชุดทรานซิชันซึ่งมีกลุ่มทรานซิชันในตัวหรือที่กำหนดเองได้

หากต้องการกำหนดชุดทรานซิชันจากคอลเล็กชันทรานซิชันใน XML ให้สร้างไฟล์ทรัพยากรในไดเรกทอรี res/transitions/ และแสดงรายการทรานซิชันในส่วนองค์ประกอบ TransitionSet ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้แสดงวิธีระบุชุดทรานซิชันที่มีลักษณะการทำงานเหมือนกับคลาส AutoTransition

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="sequential">
    <fade android:fadingMode="fade_out" />
    <changeBounds />
    <fade android:fadingMode="fade_in" />
</transitionSet>

หากต้องการเพิ่มการเปลี่ยนที่ตั้งค่าไว้เป็นออบเจ็กต์ TransitionSet ในโค้ด ให้เรียกใช้ฟังก์ชัน TransitionInflater.from() ในกิจกรรมของคุณ คลาส TransitionSet ขยายมาจากคลาส Transition คุณจึงใช้คลาสนี้กับเครื่องมือจัดการการเปลี่ยนผ่านได้เช่นเดียวกับอินสแตนซ์ Transition อื่นๆ

ใช้ทรานซิชันโดยไม่มีฉาก

การเปลี่ยนลําดับชั้นของมุมมองไม่ใช่วิธีเดียวในการแก้ไขอินเทอร์เฟซผู้ใช้ นอกจากนี้ คุณยังทำการเปลี่ยนแปลงโดยการเพิ่ม แก้ไข และนำข้อมูลพร็อพเพอร์ตี้ย่อยออกภายในลําดับชั้นปัจจุบันได้ด้วย

เช่น คุณอาจใช้การโต้ตอบการค้นหากับเลย์เอาต์เดียว เริ่มต้นด้วยเลย์เอาต์ที่แสดงช่องป้อนข้อความค้นหาและไอคอนการค้นหา หากต้องการเปลี่ยนอินเทอร์เฟซผู้ใช้ให้แสดงผลลัพธ์ ให้นำปุ่มค้นหาออกเมื่อผู้ใช้แตะโดยเรียกใช้ฟังก์ชัน ViewGroup.removeView() และเพิ่มผลการค้นหาโดยเรียกใช้ฟังก์ชัน ViewGroup.addView()

คุณใช้แนวทางนี้ได้หากทางเลือกอื่นคือมีลําดับชั้น 2 รายการที่เกือบเหมือนกัน คุณสามารถสร้างไฟล์เลย์เอาต์ 1 ไฟล์ที่มีลําดับชั้นมุมมองที่คุณแก้ไขในโค้ดแทนการสร้างและดูแลรักษาไฟล์เลย์เอาต์ 2 ไฟล์แยกกันเพื่อความแตกต่างเล็กน้อยในอินเทอร์เฟซผู้ใช้

หากทําการเปลี่ยนแปลงภายในลําดับชั้นของมุมมองปัจจุบันในลักษณะนี้ คุณไม่จําเป็นต้องสร้างฉาก แต่คุณสามารถสร้างและใช้การเปลี่ยนระหว่างลำดับชั้นการแสดงผล 2 สถานะโดยใช้การเปลี่ยนแบบล่าช้า ฟีเจอร์นี้ของเฟรมเวิร์กทรานซิชันจะเริ่มต้นจากสถานะลําดับชั้นมุมมองปัจจุบัน บันทึกการเปลี่ยนแปลงที่คุณทํากับมุมมอง และนําทรานซิชันที่แสดงภาพการเปลี่ยนแปลงเมื่อระบบวาดอินเทอร์เฟซผู้ใช้อีกครั้ง

หากต้องการสร้างการเปลี่ยนที่ล่าช้าภายในลําดับชั้นมุมมองเดียว ให้ทําตามขั้นตอนต่อไปนี้

  1. เมื่อเกิดเหตุการณ์ที่ทริกเกอร์การเปลี่ยน ให้เรียกใช้ฟังก์ชัน TransitionManager.beginDelayedTransition() โดยระบุมุมมองระดับบนสุดของมุมมองทั้งหมดที่คุณต้องการเปลี่ยนแปลงและเปลี่ยนไปใช้ เฟรมเวิร์กจะจัดเก็บสถานะปัจจุบันของมุมมองย่อยและค่าพร็อพเพอร์ตี้ของมุมมองย่อย
  2. ทำการเปลี่ยนแปลงข้อมูลพร็อพเพอร์ตี้ย่อยตาม Use Case ของคุณ เฟรมเวิร์กจะบันทึกการเปลี่ยนแปลงที่คุณทำกับมุมมองและพร็อพเพอร์ตี้ของบุตรหลาน
  3. เมื่อระบบวาดอินเทอร์เฟซผู้ใช้ใหม่ตามการเปลี่ยนแปลงของคุณ เฟรมเวิร์กจะแสดงภาพเคลื่อนไหวของการเปลี่ยนแปลงระหว่างสถานะเดิมกับสถานะใหม่

ตัวอย่างต่อไปนี้แสดงวิธีทำให้การเพิ่มมุมมองข้อความในลําดับชั้นของมุมมองเคลื่อนไหวโดยใช้การเปลี่ยนแบบเลื่อนเวลา ข้อมูลโค้ดแรกแสดงไฟล์การกำหนดเลย์เอาต์

res/layout/activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <EditText
        android:id="@+id/inputText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

ข้อมูลโค้ดถัดไปแสดงโค้ดที่สร้างภาพเคลื่อนไหวของการเพิ่มมุมมองข้อความ

กิจกรรมหลัก

Kotlin

setContentView(R.layout.activity_main)
val labelText = TextView(this).apply {
    text = "Label"
    id = R.id.text
}
val rootView: ViewGroup = findViewById(R.id.mainLayout)
val mFade: Fade = Fade(Fade.IN)
TransitionManager.beginDelayedTransition(rootView, mFade)
rootView.addView(labelText)

Java

private TextView labelText;
private Fade mFade;
private ViewGroup rootView;
...
// Load the layout.
setContentView(R.layout.activity_main);
...
// Create a new TextView and set some View properties.
labelText = new TextView(this);
labelText.setText("Label");
labelText.setId(R.id.text);

// Get the root view and create a transition.
rootView = (ViewGroup) findViewById(R.id.mainLayout);
mFade = new Fade(Fade.IN);

// Start recording changes to the view hierarchy.
TransitionManager.beginDelayedTransition(rootView, mFade);

// Add the new TextView to the view hierarchy.
rootView.addView(labelText);

// When the system redraws the screen to show this update,
// the framework animates the addition as a fade in.

กําหนด Lifecycle Callback ของการเปลี่ยนรุ่น

วงจรการเปลี่ยนจะคล้ายกับวงจรกิจกรรม ข้อมูลนี้แสดงสถานะการเปลี่ยนเฟรมเวิร์กจะตรวจสอบระหว่างช่วงเวลาที่เรียกใช้ฟังก์ชัน TransitionManager.go() กับเวลาที่ภาพเคลื่อนไหวเสร็จสมบูรณ์ เมื่ออยู่ในสถานะวงจรชีวิตของแอปที่สำคัญ เฟรมเวิร์กจะเรียกใช้การเรียกกลับที่ระบุโดยอินเทอร์เฟซ TransitionListener

การเรียกกลับวงจรการเปลี่ยนเฟสมีประโยชน์ เช่น สำหรับการคัดลอกค่าพร็อพเพอร์ตี้ของมุมมองจากลําดับชั้นมุมมองเริ่มต้นไปยังลําดับชั้นมุมมองสุดท้ายระหว่างการเปลี่ยนฉาก คุณไม่สามารถคัดลอกค่าจากมุมมองเริ่มต้นไปยังมุมมองในลําดับชั้นของมุมมองสิ้นสุดได้ เนื่องจากระบบจะไม่ขยายลําดับชั้นของมุมมองสิ้นสุดจนกว่าการเปลี่ยนผ่านจะเสร็จสมบูรณ์ แต่คุณต้องเก็บค่าไว้ในตัวแปร แล้วคัดลอกค่านั้นลงในลําดับชั้นมุมมองที่สิ้นสุดเมื่อเฟรมเวิร์กทําการเปลี่ยนเสร็จแล้ว หากต้องการรับการแจ้งเตือนเมื่อการเปลี่ยนเสร็จสมบูรณ์ ให้ใช้ฟังก์ชัน TransitionListener.onTransitionEnd() ในกิจกรรม

ดูข้อมูลเพิ่มเติมได้ที่การอ้างอิง API สำหรับคลาส TransitionListener

ข้อจำกัด

ส่วนนี้จะแสดงข้อจำกัดที่ทราบบางส่วนของเฟรมเวิร์กการเปลี่ยนผ่าน

  • ภาพเคลื่อนไหวที่ใช้กับSurfaceView อาจไม่ปรากฏอย่างถูกต้อง อินสแตนซ์ SurfaceView มีการอัปเดตจากเทรดที่ไม่ใช่ UI การอัปเดตจึงอาจไม่ซิงค์กับภาพเคลื่อนไหวของการแสดงผลอื่นๆ
  • การเปลี่ยนบางประเภทอาจไม่สร้างเอฟเฟกต์ภาพเคลื่อนไหวตามที่ต้องการเมื่อใช้กับ TextureView
  • ชั้นเรียนที่ขยาย AdapterView เช่น ListView จะจัดการมุมมองของบุตรหลานในลักษณะที่ใช้ไม่ได้กับเฟรมเวิร์กการเปลี่ยน หากคุณพยายามทำให้มุมมองเคลื่อนไหวตาม AdapterView จอแสดงผลของอุปกรณ์อาจหยุดตอบสนอง
  • หากคุณพยายามปรับขนาด TextView ด้วยภาพเคลื่อนไหว ข้อความจะปรากฏขึ้นที่ตำแหน่งใหม่ก่อนที่ระบบจะปรับขนาดออบเจ็กต์ให้เสร็จสมบูรณ์ หลีกเลี่ยงปัญหานี้โดยอย่าใช้ภาพเคลื่อนไหวในการปรับขนาดของมุมมองที่มีข้อความ