ระบบภาพเคลื่อนไหวของคุณสมบัติเป็นเฟรมเวิร์กที่มีประสิทธิภาพที่ช่วยให้คุณ เพื่อสร้างภาพเคลื่อนไหวได้เกือบทุกอย่าง คุณสามารถกําหนดภาพเคลื่อนไหวให้เปลี่ยนพร็อพเพอร์ตี้ของออบเจ็กต์เมื่อเวลาผ่านไป ไม่ว่าจะวาดบนหน้าจอหรือไม่ก็ตาม ภาพเคลื่อนไหวของพร็อพเพอร์ตี้จะเปลี่ยนแปลง ค่า (ช่องในออบเจ็กต์) ในช่วงเวลาที่ระบุ หากต้องการให้บางสิ่งเป็นภาพเคลื่อนไหว คุณต้องระบุ คุณสมบัติออบเจ็กต์ที่คุณต้องการทำให้เคลื่อนไหว เช่น ตำแหน่งของวัตถุบนหน้าจอ ระยะเวลา คุณต้องการสร้างภาพเคลื่อนไหว สำหรับค่าใด และค่าที่ต้องการให้เคลื่อนไหว
ระบบภาพเคลื่อนไหวของคุณสมบัติจะให้คุณกำหนดลักษณะเฉพาะต่อไปนี้ของ ภาพเคลื่อนไหว:
- ระยะเวลา: คุณระบุระยะเวลาของภาพเคลื่อนไหวได้ ความยาวเริ่มต้นคือ 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
ต่อไปนี้
ออบเจ็กต์ในลักษณะต่อไปนี้
- เล่น
bounceAnim
- เล่น
squashAnim1
,squashAnim2
,stretchAnim1
และstretchAnim2
ในเวลาเดียวกัน - เปิด
bounceBackAnim
- เปิด
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 และ translationYalpha
: แสดงค่าความโปร่งใสอัลฟ่าในมุมมอง ค่านี้คือ 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 ต่อไปนี้
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
หากต้องการดูแอตทริบิวต์ที่คุณใช้ในประกาศ 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 ตามโปรไฟล์