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

ลองใช้วิธีเขียน
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 ms ดังนั้นค่าของพร็อพเพอร์ตี้ในเวลาดังกล่าวจะเป็น 0.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 ระบุเป็นระยะเวลา 1000 มิลลิวินาทีเมื่อเมธอด 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 จะอัปเดตพร็อพเพอร์ตี้โดยอัตโนมัติระหว่างภาพเคลื่อนไหว ObjectAnimator จึงต้องเข้าถึงพร็อพเพอร์ตี้ด้วยเมธอดตัวตั้งค่านี้ ตัวอย่างเช่น หากชื่อพร็อพเพอร์ตี้คือ foo คุณจะต้อง มีเมธอด setFoo() หากเมธอดตัวตั้งค่านี้ไม่มีอยู่ คุณจะมีตัวเลือก 3 อย่างดังนี้
    • เพิ่มเมธอด 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 ตัวอย่างเช่น การสร้างภาพเคลื่อนไหวสำหรับพร็อพเพอร์ตี้สีของออบเจ็กต์ Drawable จะทําให้หน้าจออัปเดตเฉพาะเมื่อออบเจ็กต์นั้นวาดตัวเองใหม่ ตัวตั้งค่าพร็อพเพอร์ตี้ทั้งหมดในมุมมอง เช่น 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() คุณต้องใช้โปรแกรมรับฟังนี้หากใช้ ValueAnimator

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

คุณสามารถขยายคลาส AnimatorListenerAdapter แทนที่จะใช้อินเทอร์เฟซ Animator.AnimatorListener ได้หากไม่ต้องการนําเมธอดทั้งหมดของอินเทอร์เฟซ Animator.AnimatorListener ไปใช้ คลาส 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 - Flag ที่ระบุภาพเคลื่อนไหวที่ทำงานกับรายการที่เปลี่ยนแปลงเนื่องจากมีรายการใหม่ปรากฏในคอนเทนเนอร์
  • DISAPPEARING - Flag ที่ระบุภาพเคลื่อนไหวที่ทำงานกับรายการที่กำลังจะหายไปจากคอนเทนเนอร์
  • CHANGE_DISAPPEARING - Flag ที่ระบุภาพเคลื่อนไหวที่ทำงานกับรายการที่เปลี่ยนแปลงเนื่องจากรายการหายไปจากคอนเทนเนอร์

คุณสามารถสร้างภาพเคลื่อนไหวที่กำหนดเองสำหรับเหตุการณ์ทั้ง 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 มิลลิวินาที

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

ดังที่ตารางแสดง LinearInterpolator จะเปลี่ยนค่าด้วยความเร็วเดียวกันคือ .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);

แสดงภาพเคลื่อนไหว

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

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

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

หากต้องการสร้างภาพเคลื่อนไหวของพร็อพเพอร์ตี้ออบเจ็กต์ View เช่น สีหรือค่าการหมุน สิ่งที่คุณต้องทำคือสร้าง Property Animator และระบุพร็อพเพอร์ตี้ 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();

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 ในหลายกิจกรรมและแก้ไขลำดับภาพเคลื่อนไหวได้ง่ายขึ้น

หากต้องการแยกไฟล์ภาพเคลื่อนไหวที่ใช้ Property Animation API ใหม่ออกจากไฟล์ที่ใช้เฟรมเวิร์กภาพเคลื่อนไหวของมุมมองเดิม ตั้งแต่วันที่ 14 ตุลาคม 2013 เป็นต้นไป คุณควรบันทึกไฟล์ 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 ตามโปรไฟล์