Android allows us to work at a graphical level in two ways: at a low level ("in the kitchen"), which is with the NDK where you can program a mix between Java and C to create high-performance graphics, and with the SDK, doing it in Android which makes calls to the CPU, depending on the level of graphics we want to work with.

We can take an image and create a set of images, and we can define this process via XML or through code.

The same animation can be made in several ways; we can define the duration of the animation, the interpolation (whether the movement is linear or has a change), if the animation should repeat, if it should play in reverse, if it consists of an animated set of elements, we can also specify frames per second...

The ValueAnimator class keeps track of the animation (such as how long an object has been animated and the current value of the property being animated; this class encapsulates TimeInterpolator, which handles the interpolation of the animation, and TypeEvaluator to determine how values should be calculated (integers, floats...)), and it is started with start.

*

Difference with ViewAnimation

ViewAnimation is only used to animate objects that inherit from View (ProgressBar, TextView, etc.), like a canvas.

Furthermore, it does not expose all the properties of these objects.

Most of these classes are found in the android.animation package.

The Animator class provides the basic infrastructure to create animations, but normally we work with its subclasses:

  • ObjectAnimator: it is a subclass of ValueAnimator that allows you to set a target object and the property of an object you want to animate. This class updates the property accordingly when a new value for the animation is calculated. We can use ObjectAnimator most of the time because it makes the process of animating values in target objects much easier. However, there are times when it is better to use ValueAnimator directly because ObjectAnimator has more restrictions, such as requiring specific accessor methods on the target object.
  • AnimatorSet: Provides the mechanism to group animations together so they execute alongside each other. We can configure object animations together, sequentially, or after a specific delay. That is, determining X and Y axes.
  • ValueAnimator.

Evaluators dictate how property values being animated should be calculated. They include IntEvaluator for int properties, FloatEvaluator for float properties, ArgbEvaluator for color properties, and TypeEvaluator, which is an interface.

Interpolators indicate how values should be calculated over time. AccelerateDecelerateInterpolator, AccelerateInterpolator, and LinearInterpolator are examples of interpolators.

AccelerateDecelerateInterpolator

public float getInterpolation(float input){

return (float) (Math.cos((input+1)*Math.PI) /2.0f) + 0.5f;

}

LinearInterpolator

pubic float getInterpolation(float input){

return input;

}

msLinearacc/deacc
000
200.2.1
400.4.345
600.6.8
800.8.9
100011

Allows animating the property passed to it as an argument.

We give it set<property>() and get<property> to obtain values.

If the object does not have a setter, we can add it, create a wrapper class, or create a ValueAnimator. If only a single value is specified, it is assumed to be the end value. The object must have a get<property> to obtain the initial value.

AnimatorSet example:

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(pilota, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();*

We will have a set of listeners to know what is happening in the animation and program callbacks if we want, such as onAnimationStart(), onAnimationEnd(), onAnimationUpdate(), onAnimationRepeat(), etc. This will allow us to respond, for example, at the end of an animation (onAnimationEnd()).

ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(pilota, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { pilotes.remove(((ObjectAnimator)animation).getTarget()); }}

Keyframe animation consists of specifying keyframes formed by time/value. Each value has its own interpolator to control the behavior of the animation in the defined interval.

Methods like ofFloat(), etc., are used.

Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder rotacio = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator animacio = ObjectAnimator.ofPropertyValuesHolder(target, rotacio) animacio.setDuration (5000ms);

Objects inheriting from View (practically all those studied) have properties like translationX, translationY, rotation, rotationX, rotationY, alpha, etc., to be manipulated more easily. For example:

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

The ViewPropertyAnimator class allows animating several properties in parallel; there are three ways to do the same thing:

With ObjectAnimator:

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();With PropertyValuesHolder:

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x",50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

With ViewPropertyAnimator (does them simultaneously):

myView.animate().x(50f).y(100f);

We can also place animations in an XML file in res/anim/, for example:

animacion.xml

*<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>*

In the program we will have to put:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.anim.animacion); set.setTarget(myObject); set.start();

View animations

The view animation system can be used to perform tweened animations on view controls.

A tweened animation can perform a series of simple transformations (position, size, rotation, and transparency) on the content of a View object. Therefore, if for example we have a TextView object, the text size can be moved, rotated, grown, or reduced. If it has a background image, the background image will be transformed along with the text. The animation package provides all the classes used in a tweened animation.

A sequence of animation instructions defines the tweened animation, defined either by XML or Java code. As with defining a layout, an XML file is recommended because it is easier to read, reusable...

Animation instructions define the transformations that you want to occur, when they will happen, and how long they should take to apply. Transformations can be sequential or simultaneous; for example, you can have the content of a TextView move from left to right and then rotate 180 degrees, or do it simultaneously.

Each transformation needs a specific set of parameters for that transformation (initial size, initial angle, final angle, final size, etc.), as well as a set of common parameters (for example, start time and stop time). To make several transformations happen simultaneously, they are given the same start time, but to make them sequential, you need to calculate the start time plus the duration of the previous transformation.

The XML animation file belongs to the res/anim/ directory of the Android project.

The file must have a single root element: <alpha>, <scale>, <translate>, <rotate>, an interpolator element, or <set>, an element that holds groups of elements (which can include another <set>). By default, all animation instructions are applied simultaneously. To make them occur sequentially, you must specify the startOffset attribute.

For example:

*set android:shareInterpolator="false"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromXScale="1.0" android:toXScale="1.4" android:fromYScale="1.0" android:toYScale="0.6" android:pivotX="50%" android:pivotY="50%" android:fillAfter="false" android:duration="700" /> <set android:interpolator="@android:anim/decelerate_interpolator"> <scale android:fromXScale="1.4" android:toXScale="0.0" android:fromYScale="0.6"

android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"

android:startOffset="700" android:duration="400" /> </set> </set>*

With this XML saved as salto.xml in res/anim of the project directory, the following code will reference it and apply it to an ImageView object in the layout.

ImageView imatge = (ImageView) findViewById (R.id.imatge); Animation a = AnimationUtils.loadAnimation (això, R.anim.salt); imatge.startAnimation (a);

Drawable resource animations

Android allows loading a series of Drawable resources one after another to create an animation. This is a traditional animation in the sense that it is created with a sequence of different images, like a film roll. The AnimationDrawable class is the base for Drawable animations.

The XML file for this type of animation belongs to the res/drawable/ directory of the Android project. In this case, the instructions are in order along with the duration for each animation frame.

The XML file consists of an <animation-list> element as the root node and a series of child <item> nodes, each defining a frame: a drawable resource for the frame and the duration for each frame.

fondo.xml

<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item
android:drawable="@drawable/rocket_thrust1"
android:duration="200" />
<item
android:drawable="@drawable/rocket_thrust2"
android:duration="200" />
<item
android:drawable="@drawable/rocket_thrust3"
android:duration="200" />
</animation-list>

Code:

AnimationDrawable a; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ImageView imatge = (ImageView) findViewById(R.id.imatge); imatge.setBackgroundResource(R.drawable.fons); a = (AnimationDrawable) imatge.getBackground(); } public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { a.start(); return true; } return super.onTouchEvent(event); }

  1. Develop an application that shows a repetitive sequence animation where a text follows a box shape. Do it using Java programming and XML code.
  1. Create an animation of an image bouncing inside a container.

Solutions (Change the Android manifest for the different activities).

PDF

For more details, check Android developers.