Property Animation — un sistem de animație în Android, introdus în Android 3.0 (API 11), care modifică proprietățile reale ale obiectelor (nu doar View) într-un interval de timp dat. Spre deosebire de View Animation învechită, Property Animation schimbă câmpurile efective ale obiectului — coordonate, dimensiune, transparență, culoare — nu doar reprezentarea vizuală. Conform Google Android Developers (2026), Property Animation este utilizată în 89% din aplicațiile Android din top-100. Citiți mai multe despre alte tipuri de animație în ghidul general de animație.
Principalele
Property Animation — este un framework în Android SDK (pachetul android.animation) care animează orice proprietăți ale oricărui obiect (View, Drawable, clasă personalizată) într-un timp specificat. Spre deosebire de View Animation, care lucrează doar cu View și modifică doar reprezentarea vizuală (matrix transform), Property Animation schimbă câmpurile reale ale obiectului. Aceasta înseamnă că după animația translationX, obiectul se află efectiv în noua poziție, iar clicurile sunt procesate în locul nou.
Arhitectura Property Animation este construită pe trei clase cheie: ValueAnimator — generatorul de bază de valori, ObjectAnimator — subclasă pentru legarea la proprietatea obiectului, AnimatorSet — orchestrator pentru animația de grup. Toate trei suportă Interpolator (curba vitezei) și TypeEvaluator (regula de interpolare între valori).
Conform Android Performance Patterns (Google, 2025), Property Animation funcționează la frecvența de până la 60 FPS cu Interpolator configurat corect și fără calcule grele în onAnimationUpdate(). Pentru animații complexe (3D, fizică) se recomandă RenderThread (RenderNode Animations) în Android 12+. Property Animation rămâne alegerea principală pentru animația proprietăților View — translationX, rotationY, scaleX, alpha și altele.
ObjectAnimator — cea mai populară clasă Property Animation. Moștenește din ValueAnimator și apelează automat setter-ul proprietății specificate a obiectului cu valori animate. Pentru funcționare, ObjectAnimator necesită ca obiectul să aibă un setter public pentru proprietatea animată (de exemplu, setTranslationX(float) pentru proprietatea «translationX»).
import android.animation.ObjectAnimator
import android.view.View
// ObjectAnimator pentru translationX
val animator = ObjectAnimator.ofFloat(
myView,
"translationX",
0f,
300f
).apply {
duration = 500L
startDelay = 200L
repeatCount = 1
repeatMode = ValueAnimator.REVERSE
interpolator = FastOutSlowInInterpolator()
start()
}
Proprietăți View suportate: translationX, translationY, translationZ, rotation, rotationX, rotationY, scaleX, scaleY, alpha, x, y, elevation. ObjectAnimator.ofFloat() este utilizat pentru proprietăți float, ofInt() — pentru int, ofObject() — pentru tipuri personalizate (culoare, punct). Pentru animația culorii utilizați ofObject() cu ArgbEvaluator sau HsvEvaluator.
// ObjectAnimator cu TypeEvaluator personalizat (culoare)
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()
}
// Animația mai multor proprietăți simultan
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 — interfață pentru urmărirea evenimentelor de animație: onAnimationStart, onAnimationEnd, onAnimationCancel, onAnimationRepeat. Utilizați AnimatorListenerAdapter pentru a suprascrie doar metodele necesare. Începând cu Android 12, a fost adăugat Animator.AnimationCallback cu suport pentru corutine prin suspendAnimationFrame.
ValueAnimator — clasa de bază Property Animation care generează valori animate de la start la end într-un timp specificat. Spre deosebire de ObjectAnimator, ValueAnimator nu este legat de un obiect — el doar calculează valorile intermediare și notifică prin ascultător. Dezvoltatorul decide singur ce să facă cu valorile primite: să seteze o proprietate View, să modifice un parametru Drawable, să actualizeze desenarea personalizată în onDraw().
import android.animation.ValueAnimator
import android.view.animation.LinearInterpolator
"> ValueAnimator: animația progresului de încărcare
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() — utilizat pentru proprietăți întregi (lățime, înălțime, număr de pași). ValueAnimator.ofObject() — pentru tipuri personalizate cu TypeEvaluator. ValueAnimator.ofPropertyValuesHolder() — pentru animația paralelă a mai multor proprietăți cu un singur timer, ceea ce economisește resurse în comparație cu Animator separat pentru fiecare proprietate.
// ValueAnimator.ofObject cu 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()
}
Performanța ValueAnimator: la frecvența de 60 FPS, onAnimationUpdate este apelat la fiecare ~16.7 ms. Evitați în interiorul ascultătorului: alocarea de obiecte (creați PointF/RectF o singură dată), apelarea findViewById(), calcule grele (intrare-ieșire fișiere, rețea). Pentru animația a 20+ elemente simultane, utilizați PropertyValuesHolder într-un singur Animator în loc de 20 de Animator separate. Pentru animația cu modificarea dimensiunii, utilizați View.setLayoutParams() doar la sfârșitul animației (prin AnimatorListenerAdapter.onAnimationEnd).
AnimatorSet — orchestrator care permite rularea mai multor Animator (ObjectAnimator, ValueAnimator) într-o ordine specifică: secvențial (playSequentially), paralel (playTogether), cu întârzieri (after, before, with). AnimatorSet suportă îmbricarea — AnimatorSet poate conține alte AnimatorSet pentru scenarii complexe.
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
// AnimatorSet: animație secvențială și paralelă
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 {
// Paralel: fadeIn + slideUp
play(fadeIn).with(slideUp)
"> După: bounce cu întârziere de 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 oferă un API fluent pentru construirea lanțurilor: with() — paralel, before() — înainte, after() — după. AnimatorSet suportă cancel() pentru oprirea tuturor animațiilor din set. Pentru scenarii complexe (25+ animatoare), utilizați PropertyValuesHolder — este mai performant deoarece folosește un timer comun în loc de timere separate pentru fiecare Animator.
| Metoda Builder | Descriere | Exemplu |
|---|---|---|
| with(Animator) | Pornire paralelă cu animația curentă | play(fadeIn).with(slideUp) |
| before(Animator) | Animația curentă înainte de cea specificată | play(fadeIn).before(bounce) |
| after(Animator) | Animația curentă după cea specificată | play(bounce).after(slideUp) |
| after(Long) | Întârziere înainte de animația curentă | play(bounce).after(200L) |
Interpolator determină curba de modificare a vitezei animației de la 0 la 1. Android oferă Interpolator încorporați: LinearInterpolator (uniform), AccelerateDecelerateInterpolator (încet-rapid-încet), FastOutSlowInInterpolator (Material Design), OvershootInterpolator (cu depășirea țintei), BounceInterpolator (cu săltare), AnticipateOvershootInterpolator (cu retragere înainte de începere și depășirea țintei). Interpolator personalizat se implementează prin TimeInterpolator.
import android.animation.ObjectAnimator
import android.view.animation.BounceInterpolator
import android.view.animation.OvershootInterpolator
import android.view.animation.AnticipateOvershootInterpolator
// BounceInterpolator — efect de săltare la sfârșit
val bounceAnim = ObjectAnimator.ofFloat(myView, "translationY", 0f, -50f).apply {
duration = 600L
interpolator = BounceInterpolator()
start()
}
// AnticipateOvershoot — retragere înapoi, apoi depășire
val anticipateAnim = ObjectAnimator.ofFloat(myView, "scaleX", 1f, 1.3f).apply {
duration = 500L
interpolator = AnticipateOvershootInterpolator(2.0f)
start()
}
TypeEvaluator — interfață cu metoda evaluate(fraction, startValue, endValue) care calculează valoarea intermediară între start și end. Încorporate: ArgbEvaluator (culoare int), FloatEvaluator, IntEvaluator, PointFEvaluator, RectEvaluator. Pentru tipuri de date personalizate (de exemplu, animația unei clase personalizate cu trei câmpuri) implementați propriul TypeEvaluator. Pentru animația mai multor View cu aceleași setări, utilizați PropertyValuesHolder — acceptă un tablou de nume de proprietăți și valori corespunzătoare.
// TypeEvaluator personalizat pentru clasa 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 — performanță maximă
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()
}
Întrebări frecvente
View Animation (Tween Animation) modifică doar reprezentarea vizuală a View prin matrix transform, fără a afecta proprietățile reale ale obiectului. După animația translationX în View Animation, elementul este vizual deplasat, dar clicurile sunt procesate în poziția originală. Property Animation (ObjectAnimator) modifică proprietatea reală — după animație, elementul se află fizic în noua poziție.
Apelați animator.cancel() — animația se oprește imediat, valoarea finală nu se aplică. Apelul animator.end() — animația trece în starea finală și se oprește. Pentru AnimatorSet — set.cancel() oprește toate animațiile din set. Animator.pause() și resume() sunt disponibile pe API 19+ pentru întreruperea temporară.
Material Design recomandă: FastOutSlowInInterpolator — pentru apariția și dispariția elementelor, LinearInterpolator — pentru indicatoare de încărcare, OvershootInterpolator — pentru efecte de accent (butoane), BounceInterpolator — pentru pull-to-refresh și elemente elastice. Pentru animația de apariție de la marginea ecranului utilizați AccelerateDecelerateInterpolator.
Verificați: (1) obiectul are un setter public pentru proprietatea specificată (setPropertyName()), (2) proprietatea este scrisă în camelCase cu literă mică după «set», (3) setter-ul acceptă același tip pe care îl transmiteți (ofFloat → setPropertyName(float)). Pentru View, toate proprietățile standard (alpha, translationX, rotation etc.) au setter.
ObjectAnimator — când animează o singură proprietate standard View (alpha, translationX, rotation). ValueAnimator — când trebuie să actualizați mai multe proprietăți dintr-un singur ascultător, să animează proprietăți non-View (progres, desenare personalizată), sau când obiectul nu are setter pentru proprietatea dorită. ValueAnimator este mai flexibil, dar necesită mai mult cod pentru actualizarea manuală.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și