Please enable JavaScript to view the comments powered by Disqus.

Property Animation in Android

A - Property Animation in Android Overview

Property animation in Android is very powerful, allows you to animate almost anything!
Basically, the property animation changes object’s properties value over a specified duration.

Using property animation, you can define following characteristics of the animation:

  • Duration: By default, the animation duration is 300ms.
  • Repeat count and behaviour: You can specify the number of animation repeat and whether the animation playback in reverse.
  • Animation interpolation:  You can define how the values for property are calculated over the time
  • Animators set: You can group different animator and animators set to execute them together, in sequence or after some delay.
  • Frame refresh delay: By default, the frames will be refreshed after 10ms.

B - Compare Property Animation and View Animation

 

View Animation Property Animation
Only apply to View Be able to apply to any object
Only animate some properties of View like scaling and rotation Can animate any properties of object
Only modify where the View was drawn, not the actual View itself. For example, if you animate a View to move across the screen, the View was drawn correctly but the actual View which you can interact with is still at the old location. Modify where the object was drawn and the actual object itself
Easy to set up and write code Require more effort to implement

C - Use ValueAnimator

The ValueAnimator class lets you animate values of some type for the duration of an animation by specifying a set of int, float, or color values to animate through.

You obtain a ValueAnimator by calling one of its factory methods: ofInt(), ofFloat(), or ofObject().

private void executeAnimation() {
    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mImgSample.setAlpha(animation.getAnimatedFraction());
        }
    });
    valueAnimator.setDuration(1500);
    valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
    valueAnimator.start();
}

 

As you can see, in order to make real animation effect to the object, we also need to define the listener for ValueAnimator.

In that listener, you can obtain the calculated value for that specific frame and apply changes to your object.

D - Use ObjectAnimator

The ObjectAnimator is a subclass of the ValueAnimator and it allows you to specify the property name of the target object.

Using ObjectAnimator, you don’t need to implement the listener implicitly because the property’s value will be updated automatically.

To create a correct ObjectAnimator, you have to define:

  • Target object: The object you want to animate its property.
  • Animated property: The property you want to animate. This property must have a setter with format set<property name>. If your property doesn’t have a setter, you can:
    • Add a setter for it
    • Or use a wrapper that has right to change its values and apply ObjectAnimator to that wrapper. Make sure the wrapper class have valid setter.
    • Or use ValueAnimator instead
  • Values: This define the property value range during animation duration. If you only define 1 value, it will be the end value. In this case, the start value will be the default value when you call the getter. Because of that, your object must have the getter with format get<property name>.

Example:

private void executeAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImgSample, "rotation", 0, 360);

    objectAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            Toast.makeText(ObjectAnimatorActivity.this, "onAnimationStart", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            Toast.makeText(ObjectAnimatorActivity.this, "onAnimationEnd", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            Toast.makeText(ObjectAnimatorActivity.this, "onAnimationCancel", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
            Toast.makeText(ObjectAnimatorActivity.this, "onAnimationRepeat", Toast.LENGTH_SHORT).show();
        }
    });

    objectAnimator.setDuration(1500);
    objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
    objectAnimator.start();
}

E - Use AnimatorSet

In case you want to group some animator together to animate it at the same time or in sequence, you can use AnimatorSet to achieve that.

private void executeAnimation() {
    ObjectAnimator fadeAnim = ObjectAnimator.ofFloat(mImgSample, "alpha", 0, 1);
    fadeAnim.setDuration(1000);
    ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(mImgSample, "rotation", 0, 360);
    rotateAnim.setDuration(1000);

    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(fadeAnim).before(rotateAnim);

    ObjectAnimator fadeOutAnim = ObjectAnimator.ofFloat(mImgSample, "alpha", 0);
    AnimatorSet secondAnimatorSet = new AnimatorSet();
    secondAnimatorSet.play(fadeOutAnim).after(animatorSet);
    secondAnimatorSet.start();
}

 

F - Use Interpolator

An Interpolator define the calculation of animation value over the animating time. Interpolator allows animation has a non-linear motion like acceleration and deceleration.

Android system provides some default interpolator like:

  • AccelerateInterpolator: The rate of change starts out slowly and and then accelerates
  • DecelerateInterpolator: The rate of change starts out quickly and and then decelerates
  • AccelerateDecelerateInterpolator: The rate of change starts and ends slowly but accelerates through the middle
  • AnticipateInterpolator: The change starts backward then flings forward
  • AnticipateOvershootInterpolator: The change starts backward then flings forward and overshoots the target value and finally goes back to the final value

You can find out more about default Interpolator in android.view.animation package.

If you don’t like any default interpolator, you can create your own by implement TimeInterpolator interface.

private void executeAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImgSample, "rotation", 0, 360);
    objectAnimator.setDuration(5000);
    objectAnimator.setInterpolator(new AccelerateInterpolator());
    objectAnimator.start();
}

G - Declare Animation in XML resources

Instead of implementing the animation programmatically like above, you can declare the animation details in XML resources. This way allows you to reuse the animation and modify the animation sequence easily.

The animation XML resources are stored in res/animator/ folder.

Syntax details:

<set // Represent an AnimatorSet
  android:ordering=["together" | "sequentially"] // The order of animations in this set
  android:interpolator="@android:anim/[default_interpolator]" //The interpolator for animations in this set
  >

    <objectAnimator //Represents an ObjectAnimator
        android:propertyName="string" // The object's property to animate
        android:duration="int" // The animation duration
        android:valueFrom="float | int | color" // The property’s start value of animation
        android:valueTo="float | int | color" // The property’s end value of animation
        android:startOffset="int" // The amount of milliseconds the animation delays after animation starts
        android:repeatCount="int" // The number that animation have to repeat
        android:repeatMode=["repeat" | "reverse"] // The animation’s behaviour after reached the end of animation
        android:valueType=["intType" | "floatType"]/> //Do not specify this attribute if the value is a color

    <animator //Represents an ValueAnimator
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <set>
        ...
    </set>
</set>

Example:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <set>
        <objectAnimator
            android:duration="1500"
            android:propertyName="x"
            android:valueFrom="50"
            android:valueTo="500"
            android:valueType="floatType" />
        <objectAnimator
            android:duration="1500"
            android:propertyName="y"
            android:valueFrom="50"
            android:valueTo="800"
            android:valueType="floatType" />
    </set>
    <objectAnimator
        android:duration="1500"
        android:propertyName="alpha"
        android:valueTo="0f" />
</set>
private void executeAnimation() {
    AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.custom_animation);
    set.setTarget(mImgSample);
    set.start();
}

 H - Demo application and Source code

Please find the complete source code of this tutorial at Github:

https://github.com/trinhlbk1991/DemoPropertyAnimation