ภาพรวมภาพเคลื่อนไหวของคุณสมบัติ

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

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

ระบบภาพเคลื่อนไหวของคุณสมบัติจะให้คุณกำหนดลักษณะเฉพาะต่อไปนี้ของ ภาพเคลื่อนไหว:

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

หากต้องการดูตัวอย่างที่สมบูรณ์ของภาพเคลื่อนไหวของพร็อพเพอร์ตี้ โปรดดู คลาส ChangeColor ใน CustomTransition ตัวอย่างใน GitHub

วิธีการทำงานของภาพเคลื่อนไหวของพร็อพเพอร์ตี้

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

รูปที่ 1 ตัวอย่างภาพเคลื่อนไหวเชิงเส้น

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

รูปที่ 2 ตัวอย่างภาพเคลื่อนไหวแบบไม่เชิงเส้น

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

รูปที่ 3 วิธีคำนวณภาพเคลื่อนไหว

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

ValueAnimator จะสรุป TimeInterpolator ซึ่งกำหนดการประมาณค่าในช่วงของภาพเคลื่อนไหว และ TypeEvaluator ซึ่งจะกําหนดวิธีการคํานวณค่าของพร็อพเพอร์ตี้ ภาพเคลื่อนไหว ตัวอย่างเช่น ในรูปที่ 2 TimeInterpolator ที่ใช้จะเป็น AccelerateDecelerateInterpolator และ TypeEvaluator จะเป็น IntEvaluator

หากต้องการเริ่มภาพเคลื่อนไหว ให้สร้าง ValueAnimator และกำหนด ค่าเริ่มต้นและสิ้นสุดสำหรับพร็อพเพอร์ตี้ที่คุณต้องการให้เคลื่อนไหว พร้อมด้วยระยะเวลาของ ภาพเคลื่อนไหว เมื่อคุณเรียก start() ภาพเคลื่อนไหว เริ่มต้นขึ้น ระหว่างภาพเคลื่อนไหวทั้งหมด ValueAnimator จะคำนวณเศษส่วนที่ผ่านไป ระหว่าง 0 ถึง 1 ซึ่งขึ้นอยู่กับระยะเวลาของภาพเคลื่อนไหวและเวลาที่ผ่านไป เศษส่วนที่ผ่านไปหมายถึงเปอร์เซ็นต์ของเวลาที่ภาพเคลื่อนไหวเสร็จสมบูรณ์ ซึ่ง 0 หมายถึง 0% และ 1 หมายถึง 100% ตัวอย่างเช่น ในรูปที่ 1 ส่วนที่ผ่านไปเมื่อ t = 10 มิลลิวินาทีจะเป็น .25 เนื่องจากระยะเวลารวมคือ t = 40 มิลลิวินาที

เมื่อ ValueAnimator คำนวณเศษส่วนที่ผ่านไปเสร็จแล้ว จะเรียก TimeInterpolator ที่ตั้งไว้ในปัจจุบันเพื่อคำนวณ เศษส่วนที่ประมาณ เศษส่วนที่ประมาณจะแมปเศษส่วนที่ผ่านไปยังเศษส่วนใหม่ เศษส่วนที่คำนึงถึงการประมาณค่าในช่วงที่ตั้งค่าไว้ ตัวอย่างเช่น ในรูปที่ 2 เนื่องจากภาพเคลื่อนไหวจะเร่งความเร็วขึ้นช้าๆ เศษส่วนที่ประมาณหรือ 0 .15 จะน้อยกว่า เศษส่วนที่ผ่านไป, .25, ที่ t = 10 มิลลิวินาที ในรูปที่ 1 เศษส่วนที่ประมาณจะเท่ากับ ส่วนที่ผ่านไป

เมื่อคำนวณเศษส่วนที่ประมาณแล้ว จะเรียก ValueAnimator ครั้ง TypeEvaluator ที่เหมาะสมเพื่อคำนวณค่าของ พร็อพเพอร์ตี้ที่คุณกำลังสร้างภาพเคลื่อนไหวโดยอิงจากส่วนที่ประมาณค่า ค่าเริ่มต้น และตัวแปร ค่าสิ้นสุดของภาพเคลื่อนไหว ตัวอย่างเช่น ในรูปที่ 2 เศษส่วนที่ประมาณคือ 0 .15 เมื่อ t = 10 มิลลิวินาที ดังนั้นค่าสำหรับพร็อพเพอร์ตี้ในขณะนั้นจะเป็น .15 × (40 - 0) หรือ 6

ความแตกต่างระหว่างภาพเคลื่อนไหวของพร็อพเพอร์ตี้กับภาพเคลื่อนไหวในมุมมอง

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

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

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

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

ภาพรวม API

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

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

ตาราง 1 แอนิเมเตอร์

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

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

ตาราง 2 ผู้ประเมิน

คลาส/อินเทอร์เฟซ คำอธิบาย
IntEvaluator ผู้ประเมินเริ่มต้นที่คำนวณค่าสำหรับที่พัก int รายการ
FloatEvaluator ผู้ประเมินเริ่มต้นที่คำนวณค่าสำหรับที่พัก float รายการ
ArgbEvaluator ตัวประเมินเริ่มต้นในการคำนวณค่าสำหรับคุณสมบัติของสีที่แสดง เป็นค่าฐานสิบหก
TypeEvaluator อินเทอร์เฟซที่ให้คุณสร้างผู้ประเมินของตัวเอง ถ้ากำลังทำให้เคลื่อนไหว พร็อพเพอร์ตี้ของออบเจ็กต์ที่ไม่ใช่ int, float หรือสี คุณต้องใช้อินเทอร์เฟซ TypeEvaluator เพื่อระบุวิธี เพื่อคำนวณค่าภาพเคลื่อนไหวของคุณสมบัติออบเจ็กต์ คุณยังระบุ TypeEvaluator ที่กำหนดเองสำหรับ int, float และสีได้ด้วย หากต้องการประมวลผลประเภทเหล่านั้นให้แตกต่างจากลักษณะการทำงานเริ่มต้น ดูส่วนเกี่ยวกับการใช้ TypeEvaluator สำหรับเพิ่มเติม เกี่ยวกับวิธีเขียนผู้ประเมินที่กำหนดเอง

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

ตารางที่ 3 อินเตอร์โพเลเตอร์

คลาส/อินเทอร์เฟซ คำอธิบาย
AccelerateDecelerateInterpolator ตัวกำหนดอัตราการเปลี่ยนแปลงที่มีอัตราการเปลี่ยนแปลงเริ่มต้นและสิ้นสุดอย่างช้าๆ แต่เพิ่มขึ้นอย่างรวดเร็ว ผ่านตรงกลาง
AccelerateInterpolator ตัวการประมาณค่าที่มีอัตราการเปลี่ยนแปลงจะเริ่มอย่างช้าๆ จากนั้น เร็วขึ้น
AnticipateInterpolator ตัวกำหนดการเปลี่ยนแปลงที่การเปลี่ยนแปลงเริ่มต้นแบบถอยหลังแล้วเลื่อนไปข้างหน้า
AnticipateOvershootInterpolator ตัวกำหนดการเปลี่ยนแปลงที่การเปลี่ยนแปลงเริ่มขึ้นแบบถอยหลัง ปัดไปข้างหน้าและข้ามผ่าน ค่าเป้าหมาย แล้วกลับไปที่ค่าสุดท้าย
BounceInterpolator ตัวกำหนดการเปลี่ยนแปลงที่การเปลี่ยนแปลงจะตีกลับในช่วงท้าย
CycleInterpolator ตัวกำหนดที่มีภาพเคลื่อนไหวเล่นซ้ำตามจำนวนรอบที่ระบุ
DecelerateInterpolator ตัวกำหนดอัตราการเปลี่ยนแปลงที่อัตราการเปลี่ยนแปลงจะเริ่มต้นอย่างรวดเร็ว จากนั้น ช้าลง
LinearInterpolator ตัวกำหนดอัตราการเปลี่ยนแปลงที่มีอัตราการเปลี่ยนแปลงคงที่
OvershootInterpolator ตัวกำหนดการเปลี่ยนแปลงที่มีการเปลี่ยนแปลงไปข้างหน้าและเกินค่าสุดท้ายในตอนนั้น กลับมา
TimeInterpolator อินเทอร์เฟซที่ให้คุณติดตั้งอินเตอร์โพลเตอร์ของคุณเอง

สร้างภาพเคลื่อนไหวโดยใช้ ValueAnimator

คลาส ValueAnimator จะช่วยให้คุณทำให้ค่าบางประเภทเคลื่อนไหวสำหรับค่า ระยะเวลาของภาพเคลื่อนไหวด้วยการระบุชุด int, float หรือสี มูลค่าที่เคลื่อนไหวได้ คุณจะได้รับ ValueAnimator เมื่อโทรหา 1 เมธอดจากโรงงาน: ofInt(), ofFloat() หรือ ofObject() เช่น

Kotlin

ValueAnimator.ofFloat(0f, 100f).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();

ในโค้ดนี้ ValueAnimator จะเริ่มคำนวณค่าของฟิลด์ ระหว่าง 0 ถึง 100 เป็นระยะเวลา 1,000 มิลลิวินาที เมื่อเมธอด start() ทำงาน

นอกจากนี้คุณยังระบุประเภทที่กำหนดเองเพื่อให้เคลื่อนไหวได้ด้วยการทำสิ่งต่อไปนี้

Kotlin

ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

ในโค้ดนี้ ValueAnimator จะเริ่มคำนวณค่าของฟิลด์ ภาพเคลื่อนไหวตั้งแต่ startPropertyValue ถึง endPropertyValue โดยใช้ ตรรกะที่กำหนดโดย MyTypeEvaluator เป็นระยะเวลา 1, 000 มิลลิวินาที เมื่อเมธอด start() ทำงาน

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

Kotlin

ValueAnimator.ofObject(...).apply {
    ...
    addUpdateListener { updatedAnimation ->
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        textView.translationX = updatedAnimation.animatedValue as Float
    }
    ...
}

Java

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

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

สร้างภาพเคลื่อนไหวโดยใช้ ObjectAnimator

ObjectAnimator เป็นคลาสย่อยของ ValueAnimator (กล่าวถึงในส่วนก่อนหน้านี้) และรวมเวลาเข้าด้วยกัน การคำนวณเครื่องมือและค่าของ ValueAnimator ที่มีความสามารถในการ ทำให้พร็อพเพอร์ตี้ที่มีชื่อของออบเจ็กต์เป้าหมายเคลื่อนไหว ซึ่งจะทำให้วัตถุต่างๆ เคลื่อนไหวได้ง่ายขึ้น ไม่จำเป็นต้องใช้ ValueAnimator.AnimatorUpdateListener อีกต่อไป เพราะคุณสมบัติเคลื่อนไหวจะอัปเดตโดยอัตโนมัติ

การสร้างตัวอย่าง ObjectAnimator นั้นคล้ายกับ ValueAnimator แต่คุณยังระบุออบเจ็กต์และชื่อของพร็อพเพอร์ตี้ของออบเจ็กต์นั้นด้วย (เป็น สตริง) พร้อมกับค่าที่จะเคลื่อนไหวระหว่างรายการต่อไปนี้

Kotlin

ObjectAnimator.ofFloat(textView, "translationX", 100f).apply {
    duration = 1000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();

หากต้องการให้มีพร็อพเพอร์ตี้การอัปเดต ObjectAnimator อย่างถูกต้อง คุณจะต้องทำดังนี้

  • พร็อพเพอร์ตี้ออบเจ็กต์ที่คุณกำลังทำให้เคลื่อนไหวต้องมีฟังก์ชันตัวตั้งค่า (ในกรณีอูฐ) ในรูปแบบ set<PropertyName>() เนื่องจากObjectAnimator อัปเดตพร็อพเพอร์ตี้โดยอัตโนมัติระหว่างที่มีภาพเคลื่อนไหว พร็อพเพอร์ตี้ต้องเข้าถึงพร็อพเพอร์ตี้ได้ ด้วยเมธอด Setter นี้ ตัวอย่างเช่น หากชื่อพร็อพเพอร์ตี้คือ foo คุณจะต้อง มีเมธอด setFoo() ถ้าไม่มีเมธอด Setter นี้อยู่ คุณมี ตัวเลือก:
    • เพิ่มเมธอดตัวตั้งค่าลงในชั้นเรียนหากคุณมีสิทธิ์
    • ใช้คลาส Wrapper ที่คุณมีสิทธิ์เปลี่ยนแปลงและให้ Wrapper นั้นได้รับ ด้วยเมธอด setter ที่ถูกต้อง และส่งต่อไปยังออบเจ็กต์ต้นฉบับ
    • โปรดใช้ ValueAnimator แทน
  • หากคุณระบุเพียงค่าเดียวสำหรับพารามิเตอร์ values... ในเมธอดเริ่มต้น ObjectAnimator ค่าใดค่าหนึ่ง ระบบจะถือว่าเป็นค่าสิ้นสุดของพารามิเตอร์ ภาพเคลื่อนไหว ดังนั้น พร็อพเพอร์ตี้ออบเจ็กต์ที่คุณกำลังสร้างการเคลื่อนไหวต้องมีฟังก์ชัน Getter ที่ใช้เพื่อรับค่าเริ่มต้นของภาพเคลื่อนไหว ฟังก์ชัน Getter ต้องอยู่ในฟิลด์ ของ get<PropertyName>() ตัวอย่างเช่น หากชื่อพร็อพเพอร์ตี้คือ foo คุณต้องมีเมธอด getFoo()
  • เมธอด Getter (หากจำเป็น) และ Setter ของพร็อพเพอร์ตี้ที่คุณทำให้เคลื่อนไหวต้อง ดำเนินการในประเภทเดียวกับค่าเริ่มต้นและสิ้นสุดที่คุณระบุเป็น ObjectAnimator ตัวอย่างเช่น คุณต้องมี targetObject.setPropName(float) และ targetObject.getPropName() หากคุณสร้าง ObjectAnimator ต่อไปนี้
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
  • คุณอาจจำเป็นต้องเรียกใช้เมธอด invalidate() ในมุมมองเพื่อบังคับให้หน้าจอวาดใหม่ด้วยเมธอด อัปเดตค่าภาพเคลื่อนไหวแล้ว โดยดำเนินการใน onAnimationUpdate() Callback เช่น การทำให้คุณสมบัติสีของวัตถุที่วาดได้เคลื่อนไหวมีเพียงแค่การอัปเดต เมื่อวัตถุนั้นวาดใหม่เอง ตัวตั้งค่าพร็อพเพอร์ตี้ทั้งหมดในข้อมูลพร็อพเพอร์ตี้ เช่น setAlpha() และ setTranslationX() ทำให้มุมมองเป็นโมฆะ ดังนั้นคุณจึงไม่จำเป็นต้องทำให้มุมมองเป็นโมฆะเมื่อเรียกใช้ ด้วยค่าใหม่ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Listener โปรดดูส่วนเกี่ยวกับ Listener ภาพเคลื่อนไหว

ออกแบบภาพเคลื่อนไหวหลายภาพโดยใช้ AnimatorSet

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

ข้อมูลโค้ดต่อไปนี้เล่น Animator ต่อไปนี้ ออบเจ็กต์ในลักษณะต่อไปนี้

  1. เล่น bounceAnim
  2. เล่น squashAnim1, squashAnim2, stretchAnim1 และ stretchAnim2 ในเวลาเดียวกัน
  3. เล่น bounceBackAnim
  4. เล่น fadeAnim

Kotlin

val bouncer = AnimatorSet().apply {
    play(bounceAnim).before(squashAnim1)
    play(squashAnim1).with(squashAnim2)
    play(squashAnim1).with(stretchAnim1)
    play(squashAnim1).with(stretchAnim2)
    play(bounceBackAnim).after(stretchAnim2)
}
val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
}
AnimatorSet().apply {
    play(bouncer).before(fadeAnim)
    start()
}

Java

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

Listener ภาพเคลื่อนไหว

คุณฟังเหตุการณ์สำคัญระหว่างระยะเวลาของภาพเคลื่อนไหวกับผู้ฟังที่อธิบายไว้ด้านล่างได้

  • Animator.AnimatorListener
    • onAnimationStart() - เรียกใช้เมื่อภาพเคลื่อนไหวเริ่ม
    • onAnimationEnd() - เรียกใช้เมื่อภาพเคลื่อนไหวสิ้นสุด
    • onAnimationRepeat() - เรียกใช้เมื่อภาพเคลื่อนไหวเล่นซ้ำ
    • onAnimationCancel() - เรียกใช้เมื่อมีการยกเลิกภาพเคลื่อนไหว ภาพเคลื่อนไหวที่ยกเลิก โทรหา onAnimationEnd() ด้วย ไม่ว่าจะสิ้นสุดลงด้วยวิธีใดก็ตาม
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate() - เรียกใช้ภาพเคลื่อนไหวทุกเฟรม ฟังกิจกรรมนี้เพื่อ ใช้ค่าที่คำนวณแล้วซึ่งสร้างโดย ValueAnimator ระหว่าง ภาพเคลื่อนไหว หากต้องการใช้ค่า ให้ค้นหาออบเจ็กต์ ValueAnimator ผ่านไปยังเหตุการณ์เพื่อรับค่าภาพเคลื่อนไหวปัจจุบันด้วยเมธอด getAnimatedValue() การนำไปใช้งาน Listener เป็นสิ่งที่จำเป็นหากคุณใช้ ValueAnimator

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

คุณสามารถขยายคลาส AnimatorListenerAdapter แทน จะใช้อินเทอร์เฟซ Animator.AnimatorListener หากคุณไม่ได้ ต้องการใช้ทุกเมธอดของ Animator.AnimatorListener ของ Google ชั้นเรียน AnimatorListenerAdapter ให้ค่าว่าง ของวิธีการที่คุณสามารถเลือกลบล้างได้

ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้สร้าง AnimatorListenerAdapter สำหรับเฉพาะ onAnimationEnd() ติดต่อกลับ:

Kotlin

ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            balls.remove((animation as ObjectAnimator).target)
        }
    })
}

Java

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

สร้างภาพเคลื่อนไหวการเปลี่ยนเลย์เอาต์ของออบเจ็กต์ ViewGroup

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

คุณสามารถทำให้การเปลี่ยนแปลงเลย์เอาต์ภายใน ViewGroup เป็นภาพเคลื่อนไหวได้โดยใช้ LayoutTransition ชั้นเรียน มุมมองภายใน ViewGroup สามารถ เมื่อมีภาพเคลื่อนไหวที่ปรากฏขึ้นและหายไป เมื่อคุณเพิ่มรายการเหล่านั้นลงใน ให้นำออกจาก ViewGroup หรือเมื่อคุณเรียกใช้ setVisibility() วิธีที่มี VISIBLE, INVISIBLE หรือ GONE มุมมองที่เหลือใน ViewGroup ยังสามารถ ภาพเคลื่อนไหวไปยังตำแหน่งใหม่เมื่อคุณเพิ่มหรือนำมุมมองออก คุณสามารถกำหนด ภาพเคลื่อนไหวต่อไปนี้ในออบเจ็กต์ LayoutTransition โดยโทรไปที่ setAnimator() และการส่งผ่านในออบเจ็กต์ Animator ที่มีหนึ่งในออบเจ็กต์ ค่าคงที่ LayoutTransition ต่อไปนี้

  • APPEARING - ธงที่ระบุภาพเคลื่อนไหวที่ทำงานบนรายการที่ ที่ปรากฏในคอนเทนเนอร์
  • CHANGE_APPEARING - ธงที่ระบุภาพเคลื่อนไหวที่ทำงานบนรายการที่ เปลี่ยนแปลงเนื่องจากมีรายการใหม่ปรากฏในคอนเทนเนอร์
  • DISAPPEARING - ธงที่ระบุภาพเคลื่อนไหวที่ทำงานบนรายการที่ หายไปจากคอนเทนเนอร์
  • CHANGE_DISAPPEARING - ธงที่ระบุภาพเคลื่อนไหวที่ทำงานบนรายการที่ เปลี่ยนแปลงไปเนื่องจากรายการหายไปจากคอนเทนเนอร์

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

วิธีตั้งค่าแอตทริบิวต์ android:animateLayoutchanges เป็น true สำหรับแอตทริบิวต์ ViewGroup ให้ดำเนินการดังนี้

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

การตั้งค่าแอตทริบิวต์นี้เป็น "จริง" จะทำให้ภาพเคลื่อนไหวของมุมมองที่เพิ่มหรือนำออกจาก ViewGroup รวมถึงข้อมูลพร็อพเพอร์ตี้ที่เหลือใน ViewGroup

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

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

คุณกำหนด StateListAnimator ในทรัพยากร XML ที่มีรูทได้ องค์ประกอบ <selector> และองค์ประกอบย่อย <item> ที่แต่ละองค์ประกอบระบุ สถานะการดูอื่นๆ ที่กำหนดโดยคลาส StateListAnimator ชิ้น <item> มีคําจํากัดความของชุดภาพเคลื่อนไหวของพร็อพเพอร์ตี้

ตัวอย่างเช่น ไฟล์ต่อไปนี้สร้างตัวสร้างภาพเคลื่อนไหวของรายการสถานะที่เปลี่ยนแปลงสเกล x และ y ของมุมมองเมื่อกด

res/xml/animate_scale.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the pressed state; increase x and y size to 150% -->
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
        </set>
    </item>
    <!-- the default, non-pressed state; set x and y size to 100% -->
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>

หากต้องการแนบตัวสร้างภาพเคลื่อนไหวรายการรัฐลงในมุมมอง ให้เพิ่มพารามิเตอร์ android:stateListAnimator ดังนี้

<Button android:stateListAnimator="@xml/animate_scale"
        ... />

ตอนนี้ จะมีการใช้ภาพเคลื่อนไหวที่กำหนดไว้ใน animate_scale.xml เมื่อของปุ่มนี้ การเปลี่ยนแปลงสถานะ

หรือหากต้องการกำหนดตัวสร้างภาพเคลื่อนไหวรายการสถานะให้กับมุมมองในโค้ดของคุณ ให้ใช้ AnimatorInflater.loadStateListAnimator() และกำหนดผู้สร้างภาพเคลื่อนไหวให้กับ โดยใช้เมธอด View.setStateListAnimator()

หรือแทนที่จะทำให้คุณสมบัติของมุมมองเคลื่อนไหวได้ คุณสามารถเล่นภาพเคลื่อนไหวที่ถอนออกได้ระหว่าง การเปลี่ยนแปลงสถานะ โดยใช้ AnimatedStateListDrawable วิดเจ็ตระบบบางส่วนใน Android 5.0 จะใช้ภาพเคลื่อนไหวเหล่านี้โดยค่าเริ่มต้น ตัวอย่างต่อไปนี้จะแสดงวิธีการ เพื่อกำหนด AnimatedStateListDrawable เป็นทรัพยากร XML:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

ใช้ TypeEvaluator

คุณสร้างภาพเคลื่อนไหวในประเภทที่ระบบ Android ไม่รู้จักได้ ผู้ประเมินโดยใช้อินเทอร์เฟซ TypeEvaluator ประเภทที่ ระบบ Android จะรู้จักกันในชื่อ int, float หรือสี รองรับโดยประเภท IntEvaluator, FloatEvaluator และ ArgbEvaluator ผู้ประเมิน

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

Kotlin

private class FloatEvaluator : TypeEvaluator<Any> {

    override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any {
        return (startValue as Number).toFloat().let { startFloat ->
            startFloat + fraction * ((endValue as Number).toFloat() - startFloat)
        }
    }

}

Java

public class FloatEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

หมายเหตุ: เมื่อ ValueAnimator (หรือ ObjectAnimator) ทำงาน ระบบจะคำนวณเศษส่วนที่ผ่านไปในปัจจุบันของ ภาพเคลื่อนไหว (ค่าระหว่าง 0 ถึง 1) แล้วคำนวณรูปแบบการประมาณค่านั้น คุณกำลังใช้อินเตอร์โพลเตอร์ชนิดใด เศษส่วนที่ประมาณคือสิ่งที่ TypeEvaluator ได้รับผ่านพารามิเตอร์ fraction ไม่จำเป็นต้องคำนึงถึงตัวการประมาณค่าในช่วงเมื่อคำนวณค่าแบบเคลื่อนไหว

ใช้อินเตอร์โพเลเตอร์

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

ตัวแปลงสัญญาณในระบบภาพเคลื่อนไหวจะได้รับเศษส่วนจากแอนิเมเตอร์ที่แสดงถึง เวลาที่ใช้ไปของภาพเคลื่อนไหว ตัวแปลงกลางจะปรับแต่งเศษส่วนนี้ให้ตรงกับประเภทของ ภาพเคลื่อนไหวที่วางแผนไว้ ระบบ Android มีชุดอินเตอร์โพเลเตอร์ทั่วไปใน android.view.animation package หากไม่มีข้อใดที่ตรงกับ คุณสามารถใช้อินเทอร์เฟซ TimeInterpolator และสร้าง ของตัวเอง

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

AccelerateDecelerateInterpolator

Kotlin

override fun getInterpolation(input: Float): Float =
        (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f

Java

@Override
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

LinearInterpolator

Kotlin

override fun getInterpolation(input: Float): Float = input

Java

@Override
public float getInterpolation(float input) {
    return input;
}

ตารางต่อไปนี้แสดงค่าโดยประมาณที่คำนวณจาก ตัวกำหนดช่วงสำหรับภาพเคลื่อนไหวที่ยาวนาน 1,000 มิลลิวินาที:

ผ่านไปแล้ว ms เศษส่วนที่ผ่านไป/เศษส่วนแทรก (เชิงเส้น) เศษส่วนโดยประมาณ (เร่ง/ลด)
0 0 0
200 .2 .1
400 .4 .345
600 6 วินาที .8
800 .8 .9
1000 1 1

ตามตารางที่ปรากฏ LinearInterpolator จะเปลี่ยนค่า ที่ความเร็วเดียวกัน นั่นคือ 0.2 สำหรับทุก 200 มิลลิวินาทีที่ผ่านไป AccelerateDecelerateInterpolator จะเปลี่ยนค่าให้เร็วกว่า LinearInterpolator ระหว่าง 200 ถึง 600 มิลลิวินาที และช้าลงระหว่าง 600 มิลลิวินาทีถึง 1,000 มิลลิวินาที

ระบุคีย์เฟรม

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

หากต้องการสร้างอินสแตนซ์ของออบเจ็กต์ Keyframe คุณต้องใช้ค่าจากโรงงาน เมธอด ofInt(), ofFloat() หรือ ofObject() เพื่อรับประเภท Keyframe ที่เหมาะสม จากนั้นคุณจึงโทร เมธอด ofKeyframe() จากโรงงานเพื่อ รับออบเจ็กต์ PropertyValuesHolder เมื่อมีออบเจ็กต์แล้ว คุณสามารถ รับตัวสร้างภาพเคลื่อนไหวโดยการส่งผ่านในออบเจ็กต์ PropertyValuesHolder และ เพื่อให้วัตถุเคลื่อนไหวได้ ข้อมูลโค้ดต่อไปนี้แสดงวิธีดำเนินการ

Kotlin

val kf0 = Keyframe.ofFloat(0f, 0f)
val kf1 = Keyframe.ofFloat(.5f, 360f)
val kf2 = Keyframe.ofFloat(1f, 0f)
val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2)
ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply {
    duration = 5000
}

Java

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);

มุมมองแบบเคลื่อนไหว

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

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

  • translationX และ translationY: พร็อพเพอร์ตี้เหล่านี้ควบคุมว่า มุมมองอยู่ในตำแหน่งเดลต้าจากพิกัดด้านซ้ายและด้านบน ซึ่งกำหนดตามการจัดวาง คอนเทนเนอร์
  • rotation, rotationX และ rotationY: พร็อพเพอร์ตี้เหล่านี้ ควบคุมการหมุนในแบบ 2 มิติ (rotation พร็อพเพอร์ตี้) และ 3 มิติรอบจุด Pivot
  • scaleX และ scaleY: พร็อพเพอร์ตี้เหล่านี้จะควบคุมการปรับขนาด 2 มิติของ ดูรอบๆ จุด Pivot
  • pivotX และ pivotY: พร็อพเพอร์ตี้เหล่านี้จะควบคุมตำแหน่งของ จุดหมุน ซึ่งมีการเปลี่ยนการหมุนและการปรับขนาดเกิดขึ้น โดยค่าเริ่มต้น การเปลี่ยนแนวทางเนื้อหา จุดจะอยู่ตรงกลางของวัตถุ
  • x และ y: คุณสมบัติของยูทิลิตีที่เรียบง่ายเพื่ออธิบาย ตำแหน่งสุดท้ายของมุมมองในคอนเทนเนอร์ ซึ่งเป็นผลรวมของค่าด้านซ้ายและค่าด้านบนและ ค่า X และ translateY
  • alpha: แสดงความโปร่งใสของอัลฟ่าในมุมมอง ค่านี้คือ 1 (ทึบแสง) โดยค่าเริ่มต้น ซึ่งมีค่า 0 แสดงถึงความโปร่งใสโดยสมบูรณ์ (มองไม่เห็น)

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

Kotlin

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)

Java

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการสร้างภาพเคลื่อนไหว โปรดดูส่วนต่างๆ เกี่ยวกับการสร้างภาพเคลื่อนไหวด้วย ValueAnimator และ ObjectAnimator

สร้างภาพเคลื่อนไหวโดยใช้ ViewPropertyAnimator

ViewPropertyAnimator มีวิธีทำให้หลาย คุณสมบัติของ View พร้อมกันโดยใช้ Animator ที่สำคัญเพียงรายการเดียว ออบเจ็กต์ ซึ่งมีลักษณะคล้ายกับ ObjectAnimator เนื่องจากมีการแก้ไข ค่าที่แท้จริงของคุณสมบัติของมุมมอง แต่จะมีประสิทธิภาพมากกว่าเมื่อทำให้คุณสมบัติจำนวนมากเคลื่อนไหว ครั้งเดียว นอกจากนี้ รหัสสำหรับการใช้ ViewPropertyAnimator ยังมีประโยชน์อย่างมาก กระชับและอ่านง่ายขึ้น ข้อมูลโค้ดต่อไปนี้แสดงความแตกต่างในการใช้ ออบเจ็กต์ ObjectAnimator รายการ รายการเดียว ObjectAnimator และ ViewPropertyAnimator เมื่อ การทำให้พร็อพเพอร์ตี้ x และ y ของข้อมูลพร็อพเพอร์ตี้เคลื่อนไหวพร้อมกัน

ออบเจ็กต์ ObjectAnimator หลายรายการ

Kotlin

val animX = ObjectAnimator.ofFloat(myView, "x", 50f)
val animY = ObjectAnimator.ofFloat(myView, "y", 100f)
AnimatorSet().apply {
    playTogether(animX, animY)
    start()
}

Java

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

One ObjectAnimator

Kotlin

val pvhX = PropertyValuesHolder.ofFloat("x", 50f)
val pvhY = PropertyValuesHolder.ofFloat("y", 100f)
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()

Java

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();

ViewPropertyAnimator

Kotlin

myView.animate().x(50f).y(100f)

Java

myView.animate().x(50f).y(100f);

ดูรายละเอียดเพิ่มเติมเกี่ยวกับ ViewPropertyAnimator ได้ที่นักพัฒนาแอป Android ที่เกี่ยวข้อง บล็อก โพสต์

ประกาศภาพเคลื่อนไหวใน XML

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

หากต้องการแยกความแตกต่างระหว่างไฟล์ภาพเคลื่อนไหวที่ใช้ API ภาพเคลื่อนไหวของพร็อพเพอร์ตี้ใหม่กับไฟล์ที่ใช้องค์ประกอบ เฟรมเวิร์กดูภาพเคลื่อนไหวแบบเดิม ตั้งแต่ Android 3.1 เป็นต้นไป คุณควรบันทึกไฟล์ XML สำหรับภาพเคลื่อนไหวของพร็อพเพอร์ตี้ในไดเรกทอรี res/animator/

คลาสภาพเคลื่อนไหวของพร็อพเพอร์ตี้ต่อไปนี้รองรับการประกาศ XML ด้วยฟังก์ชัน แท็ก XML ต่อไปนี้:

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

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>

เพื่อเรียกใช้ภาพเคลื่อนไหวนี้ คุณต้องเพิ่มทรัพยากร XML ในโค้ดของคุณให้สูงเกินจริงให้เป็นออบเจ็กต์ AnimatorSet จากนั้นตั้งค่าออบเจ็กต์เป้าหมายสำหรับภาพเคลื่อนไหวทั้งหมด ก่อนเริ่มตั้งค่าภาพเคลื่อนไหว การเรียกใช้ setTarget() จะตั้งค่าออบเจ็กต์เป้าหมายเดียวสำหรับผู้เผยแพร่โฆษณาย่อยทั้งหมดของ AnimatorSet เพื่ออำนวยความสะดวก โค้ดต่อไปนี้แสดงวิธีดำเนินการ

Kotlin

(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply {
    setTarget(myObject)
    start()
}

Java

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.animator.property_animator);
set.setTarget(myObject);
set.start();

คุณยังประกาศ ValueAnimator ใน XML ได้ด้วย เช่น ที่แสดงในตัวอย่างต่อไปนี้

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0f"
    android:valueTo="-100f" />

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

Kotlin

(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply {
    addUpdateListener { updatedAnimation ->
        textView.translationX = updatedAnimation.animatedValue as Float
    }

    start()
}

Java

ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
        R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

xmlAnimator.start();

สำหรับข้อมูลเกี่ยวกับไวยากรณ์ XML สำหรับการกำหนดภาพเคลื่อนไหวของพร็อพเพอร์ตี้ โปรดดูภาพเคลื่อนไหว

ผลกระทบที่อาจเกิดขึ้นกับประสิทธิภาพ UI

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

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