Property Animation คือระบบการเคลื่อนไหวใน Android ที่เปิดตัวใน Android 3.0 (API 11) ซึ่งเปลี่ยนคุณสมบัติจริงของวัตถุ (ไม่ใช่แค่ View) ตามช่วงเวลาที่กำหนด แตกต่างจาก View Animation แบบเก่า Property Animation จะเปลี่ยนฟิลด์จริงของวัตถุ — พิกัด, ขนาด, ความโปร่งใส, สี — ไม่ใช่แค่การแสดงผลทางภาพเท่านั้น ตามข้อมูลจาก Google Android Developers (2026) Property Animation ถูกใช้ใน 89% ของแอป Android ใน 100 อันดับแรก เรียนรู้เพิ่มเติมเกี่ยวกับการเคลื่อนไหวประเภทอื่นๆ ใน คู่มือการเคลื่อนไหวทั่วไป
ประเด็นสำคัญ
Property Animation คือเฟรมเวิร์กใน Android SDK (แพ็คเกจ android.animation) ที่เคลื่อนไหวคุณสมบัติใดๆ ของวัตถุใดๆ (View, Drawable, คลาสที่กำหนดเอง) ภายในเวลาที่กำหนด แตกต่างจาก View Animation ที่ทำงานเฉพาะกับ View และเปลี่ยนแปลงเฉพาะการแสดงผลทางภาพ (การแปลงเมทริกซ์) Property Animation จะปรับเปลี่ยนฟิลด์จริงของวัตถุ ซึ่งหมายความว่าหลังจากการเคลื่อนไหว translationX วัตถุจะอยู่ในตำแหน่งใหม่จริงๆ และการคลิกจะถูกประมวลผลที่ตำแหน่งใหม่
สถาปัตยกรรมของ Property Animation สร้างขึ้นบนสามคลาสหลัก: ValueAnimator — ตัวสร้างค่าพื้นฐาน, ObjectAnimator — คลาสย่อยสำหรับการเชื่อมต่อกับคุณสมบัติของวัตถุ, AnimatorSet — ตัวประสานงานสำหรับการเคลื่อนไหวแบบกลุ่ม ทั้งสามรองรับ Interpolator (เส้นโค้งความเร็ว) และ TypeEvaluator (กฎการประมาณค่าระหว่างค่า)
ตามข้อมูลจาก Android Performance Patterns (Google, 2025) Property Animation ทำงานได้ถึง 60 FPS เมื่อกำหนดค่า Interpolator อย่างถูกต้องและไม่มีการคำนวณหนักใน onAnimationUpdate() สำหรับการเคลื่อนไหวที่ซับซ้อน (3D, ฟิสิกส์) แนะนำให้ใช้ RenderThread (RenderNode Animations) ใน Android 12+ Property Animation ยังคงเป็นตัวเลือกหลักสำหรับการเคลื่อนไหวคุณสมบัติ View — translationX, rotationY, scaleX, alpha และอื่นๆ
ObjectAnimator เป็นคลาสที่ได้รับความนิยมมากที่สุดของ Property Animation โดยสืบทอดจาก ValueAnimator และเรียก setter ของคุณสมบัติที่ระบุของวัตถุโดยอัตโนมัติด้วยค่าเคลื่อนไหว เพื่อให้ ObjectAnimator ทำงาน วัตถุต้องมี setter สาธารณะสำหรับคุณสมบัติที่กำลังเคลื่อนไหว (เช่น setTranslationX(float) สำหรับคุณสมบัติ “translationX”)
import android.animation.ObjectAnimator
import android.view.View
// ObjectAnimator สำหรับ translationX
val animator = ObjectAnimator.ofFloat(
myView,
"translationX",
0f,
300f
).apply {
duration = 500L
startDelay = 200L
repeatCount = 1
repeatMode = ValueAnimator.REVERSE
interpolator = FastOutSlowInInterpolator()
start()
}
คุณสมบัติ View ที่รองรับ: translationX, translationY, translationZ, rotation, rotationX, rotationY, scaleX, scaleY, alpha, x, y, elevation ObjectAnimator.ofFloat() ใช้สำหรับคุณสมบัติ float, ofInt() สำหรับ int, ofObject() สำหรับประเภทที่กำหนดเอง (สี, จุด) สำหรับการเคลื่อนไหวสี ให้ใช้ ofObject() กับ ArgbEvaluator หรือ HsvEvaluator
// ObjectAnimator กับ TypeEvaluator ที่กำหนดเอง (สี)
import android.animation.ObjectAnimator
import android.animation.ArgbEvaluator
import android.graphics.Color
val colorAnim = ObjectAnimator.ofObject(
myView,
"backgroundColor",
ArgbEvaluator(),
Color.BLUE,
Color.RED
).apply {
duration = 1000L
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.REVERSE
start()
}
// การเคลื่อนไหวหลายคุณสมบัติพร้อมกัน
val scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 1f, 1.5f)
val scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 1f, 1.5f)
val alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1f, 0.5f)
AnimatorListener — อินเทอร์เฟซสำหรับติดตามเหตุการณ์การเคลื่อนไหว: onAnimationStart, onAnimationEnd, onAnimationCancel, onAnimationRepeat ใช้ AnimatorListenerAdapter เพื่อแทนที่เฉพาะเมธอดที่จำเป็นเท่านั้น ตั้งแต่ Android 12 เป็นต้นมา มีการเพิ่ม Animator.AnimationCallback ที่รองรับ coroutine ผ่าน suspendAnimationFrame
ValueAnimator เป็นคลาสพื้นฐานของ Property Animation ที่สร้างค่าเคลื่อนไหวจากเริ่มต้นถึงสิ้นสุดตามช่วงเวลาที่กำหนด แตกต่างจาก ObjectAnimator ตรงที่ ValueAnimator ไม่ได้ยึดติดกับวัตถุ — มันเพียงคำนวณค่ากลางและแจ้งเตือนผ่านผู้ฟัง นักพัฒนาตัดสินใจว่าจะทำอย่างไรกับค่าที่ได้รับ: ตั้งค่าคุณสมบัติ View, เปลี่ยนพารามิเตอร์ Drawable, อัปเดตการวาดแบบกำหนดเองใน onDraw()
import android.animation.ValueAnimator
import android.view.animation.LinearInterpolator
"> ValueAnimator: แอนิเมชันความคืบหน้าการโหลด
val valueAnimator = ValueAnimator.ofFloat(0f, 100f).apply {
duration = 2000L
interpolator = LinearInterpolator()
repeatCount = ValueAnimator.INFINITE
addUpdateListener { animator ->
val progress = animator.animatedValue as Float
progressBar.progress = progress.toInt()
progressText.text = "${progress.toInt()}%"
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationRepeat(animation: Animator) {
Log.d("Anim", "Progress animation restarted")
}
})
start()
}
ValueAnimator.ofInt() — ใช้สำหรับคุณสมบัติจำนวนเต็ม (ความกว้าง, ความสูง, จำนวนขั้นตอน) ValueAnimator.ofObject() — สำหรับประเภทที่กำหนดเองกับ TypeEvaluator ValueAnimator.ofPropertyValuesHolder() — สำหรับการเคลื่อนไหวแบบขนานของคุณสมบัติหลายรายการด้วยตัวจับเวลาเดียว ประหยัดทรัพยากรเมื่อเทียบกับการใช้ Animator แยกสำหรับแต่ละคุณสมบัติ
// ValueAnimator.ofObject กับ PointEvaluator
import android.animation.ValueAnimator
import android.graphics.PointF
import android.animation.PointFEvaluator
val pointAnim = ValueAnimator.ofObject(
PointFEvaluator(),
PointF(0f, 0f),
PointF(300f, 500f)
).apply {
duration = 1000L
addUpdateListener { animator ->
val point = animator.animatedValue as PointF
movingView.x = point.x
movingView.y = point.y
}
start()
}
ประสิทธิภาพของ ValueAnimator: ที่ 60 FPS onAnimationUpdate จะถูกเรียกทุกๆ ~16.7 มิลลิวินาที หลีกเลี่ยงภายในผู้ฟัง: การจัดสรรวัตถุ (สร้าง PointF/RectF ครั้งเดียว), การเรียก findViewById(), การคำนวณหนัก (I/O ไฟล์, เครือข่าย) สำหรับการเคลื่อนไหว 20+ องค์ประกอบพร้อมกัน ให้ใช้ PropertyValuesHolder ใน Animator เดียวแทน 20 Animator แยกกัน สำหรับการเคลื่อนไหวที่เปลี่ยนขนาด ให้ใช้ View.setLayoutParams() เฉพาะตอนท้ายการเคลื่อนไหวเท่านั้น (ผ่าน AnimatorListenerAdapter.onAnimationEnd)
AnimatorSet คือตัวประสานงานที่อนุญาตให้เรียกใช้หลายอินสแตนซ์ของ Animator (ObjectAnimator, ValueAnimator) ตามลำดับที่กำหนด: ตามลำดับ (playSequentially), ขนานกัน (playTogether), กับความล่าช้า (after, before, with) AnimatorSet รองรับการซ้อนกัน — AnimatorSet สามารถมี AnimatorSet อื่นๆ สำหรับสถานการณ์ที่ซับซ้อน
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
// AnimatorSet: การเคลื่อนไหวตามลำดับและขนาน
val fadeIn = ObjectAnimator.ofFloat(myView, "alpha", 0f, 1f)
val slideUp = ObjectAnimator.ofFloat(myView, "translationY", 100f, 0f)
val bounce = ObjectAnimator.ofFloat(myView, "scaleX", 1f, 1.1f, 1f)
val animatorSet = AnimatorSet().apply {
// ขนาน: fadeIn + slideUp
play(fadeIn).with(slideUp)
"> หลังจาก: bounce ด้วยดีเลย์ 200ms
play(bounce).after(200L)
duration = 400L
interpolator = FastOutSlowInInterpolator()
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
Log.d("Anim", "Set completed")
}
})
start()
}
AnimatorSet.Builder ให้ API แบบลื่นไหลสำหรับสร้างลูกโซ่: with() — ขนานกัน, before() — ก่อน, after() — หลังจาก AnimatorSet รองรับ cancel() สำหรับหยุดการเคลื่อนไหวทั้งหมดในชุด สำหรับสถานการณ์ที่ซับซ้อน (25+ Animator) ให้ใช้ PropertyValuesHolder — มีประสิทธิภาพมากกว่าเพราะใช้ตัวจับเวลาแบบใช้ร่วมกันเดียวแทนที่จะแยกสำหรับแต่ละ Animator
| เมธอด Builder | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| with(Animator) | ทำงานขนานกับการเคลื่อนไหวปัจจุบัน | play(fadeIn).with(slideUp) |
| before(Animator) | การเคลื่อนไหวปัจจุบันก่อนที่ระบุ | play(fadeIn).before(bounce) |
| after(Animator) | การเคลื่อนไหวปัจจุบันหลังจากที่ระบุ | play(bounce).after(slideUp) |
| after(Long) | ความล่าช้าก่อนการเคลื่อนไหวปัจจุบัน | play(bounce).after(200L) |
Interpolator กำหนดเส้นโค้งความเร็วของการเคลื่อนไหวจาก 0 ถึง 1 Android มี Interpolator ในตัว: LinearInterpolator (สม่ำเสมอ), AccelerateDecelerateInterpolator (ช้า-เร็ว-ช้า), FastOutSlowInInterpolator (Material Design), OvershootInterpolator (เกินเป้าหมาย), BounceInterpolator (กระเด้ง), AnticipateOvershootInterpolator (ดึงกลับก่อนเริ่มและเกินเป้าหมาย) Interpolator ที่กำหนดเองถูก implement ผ่าน TimeInterpolator
import android.animation.ObjectAnimator
import android.view.animation.BounceInterpolator
import android.view.animation.OvershootInterpolator
import android.view.animation.AnticipateOvershootInterpolator
// BounceInterpolator — เอฟเฟกต์กระเด้งในตอนท้าย
val bounceAnim = ObjectAnimator.ofFloat(myView, "translationY", 0f, -50f).apply {
duration = 600L
interpolator = BounceInterpolator()
start()
}
// AnticipateOvershoot — ดึงกลับ แล้วเกินเป้าหมาย
val anticipateAnim = ObjectAnimator.ofFloat(myView, "scaleX", 1f, 1.3f).apply {
duration = 500L
interpolator = AnticipateOvershootInterpolator(2.0f)
start()
}
TypeEvaluator — อินเทอร์เฟซที่มีเมธอด evaluate(fraction, startValue, endValue) ซึ่งคำนวณค่ากลางระหว่างค่าเริ่มต้นและค่าสิ้นสุด ในตัว: ArgbEvaluator (สี int), FloatEvaluator, IntEvaluator, PointFEvaluator, RectEvaluator สำหรับประเภทข้อมูลที่กำหนดเอง (เช่น การเคลื่อนไหวคลาสที่กำหนดเองที่มีสามฟิลด์) ให้ implement TypeEvaluator ของคุณเอง สำหรับการเคลื่อนไหวหลาย Views ด้วยการตั้งค่าเดียวกัน ให้ใช้ PropertyValuesHolder — มันรับอาร์เรย์ของชื่อคุณสมบัติและค่าที่สอดคล้องกัน
// TypeEvaluator ที่กำหนดเองสำหรับคลาส ProgressState
data class ProgressState(val progress: Float, val color: Int)
class ProgressEvaluator : TypeEvaluator<ProgressState> {
override fun evaluate(
fraction: Float,
startValue: ProgressState,
endValue: ProgressState
): ProgressState {
val progress = startValue.progress + fraction * (endValue.progress - startValue.progress)
val color = ArgbEvaluator().evaluate(
fraction, startValue.color, endValue.color
) as Int
return ProgressState(progress, color)
}
}
"> PropertyValuesHolder — ประสิทธิภาพสูงสุด
val pvh1 = PropertyValuesHolder.ofFloat("scaleX", 1f, 1.5f)
val pvh2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 1.5f)
val pvhAnim = ObjectAnimator.ofPropertyValuesHolder(myView, pvh1, pvh2).apply {
duration = 300L
start()
}
คำถามที่พบบ่อย
View Animation (Tween Animation) เปลี่ยนแปลงเฉพาะการแสดงผลทางภาพของ View ผ่านการแปลงเมทริกซ์ โดยไม่ส่งผลต่อคุณสมบัติจริงของวัตถุ หลังจากการเคลื่อนไหว translationX ใน View Animation องค์ประกอบถูกเลื่อนในทางภาพ แต่การคลิกยังคงถูกประมวลผลที่ตำแหน่งเดิม Property Animation (ObjectAnimator) เปลี่ยนคุณสมบัติจริง — หลังการเคลื่อนไหว องค์ประกอบจะอยู่ที่ตำแหน่งใหม่ทางกายภาพ
เรียก animator.cancel() — การเคลื่อนไหวหยุดทันที ค่าสุดท้ายจะไม่ถูกนำไปใช้ การเรียก animator.end() — การเคลื่อนไหวเปลี่ยนไปสู่สถานะสุดท้ายและหยุด สำหรับ AnimatorSet — set.cancel() หยุดการเคลื่อนไหวทั้งหมดในชุด Animator.pause() และ resume() พร้อมใช้งานบน API 19+ สำหรับการหยุดชั่วคราว
Material Design แนะนำ: FastOutSlowInInterpolator — สำหรับการเคลื่อนไหวการปรากฏและการหายไปขององค์ประกอบ, LinearInterpolator — สำหรับตัวบ่งชี้การโหลด, OvershootInterpolator — สำหรับเอฟเฟกต์เน้น (ปุ่ม), BounceInterpolator — สำหรับ pull-to-refresh และองค์ประกอบสปริง สำหรับการเคลื่อนไหวที่ปรากฏจากนอกหน้าจอ ให้ใช้ AccelerateDecelerateInterpolator
ตรวจสอบ: (1) วัตถุมี setter สาธารณะสำหรับคุณสมบัติที่ระบุ (setPropertyName()), (2) คุณสมบัติเขียนในรูปแบบ camelCase ด้วยตัวอักษรพิมพ์เล็กหลัง “set”, (3) setter รับชนิดเดียวกับที่คุณส่ง (ofFloat → setPropertyName(float)) สำหรับ View คุณสมบัติมาตรฐานทั้งหมด (alpha, translationX, rotation ฯลฯ) มี setter
ObjectAnimator — เมื่อคุณกำลังเคลื่อนไหวคุณสมบัติ View มาตรฐานเดี่ยว (alpha, translationX, rotation) ValueAnimator — เมื่อคุณต้องการอัปเดตหลายคุณสมบัติจากผู้ฟังเดียว, เคลื่อนไหวคุณสมบัติที่ไม่ใช่ View (ความคืบหน้า, การวาดแบบกำหนดเอง), หรือเมื่อวัตถุไม่มี setter สำหรับคุณสมบัติที่ต้องการ ValueAnimator ยืดหยุ่นกว่า แต่ต้องใช้โค้ดมากกว่าสำหรับการอัปเดตด้วยตนเอง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม