Making simple animations in Android with Kotlin - Java 9

- Andrés Cruz

En español
Making simple animations in Android with Kotlin - Java 9

Animations are a fundamental point today to give presence when loading data, transition images between screens, etc., and it is a fundamental point for "Android developers" and not make interfaces so "boring"; make animations like the following, in which we vary the translation in the Y axis and the opacity from zero to one:

traslación y opacidad Android animación

Or it is in which we vary only the translation in the X axis:

traslación Android animación

Or is it in which we vary only the opacity:

opacidad Android animación

It is really easy and we can even execute them in parallel in the same element or resource of a view.

One of the great principles of Material Design is the use of animations as a fundamental element to interact with the user through the UI depending on the interactivity that the user performs with the application.

For the animations in Android that in the end are simple transitions between one state and another, we are going to make use of the ObjectAnimator that provide functionalities to animate views through a target or objective that has been defined with the PropertyValuesHolder that are the way in which we indicate the property and the values that we want to animate...

For example, the property that we want to animate could be the opacity and the value of zero as the initial value and one to make it completely visible; then we go from a state in which the view is invisible to completely visible (of course, it can be the other way around or stay in the middle and be semi-visible, etc).

Types of animations in Android: Animations using ObjectAnimator

Once the theoretical framework is clear, which in summary is to define the property and the associated values, now we will see what types of animations we can do, that is, what we can animate and what their values could be.

Animating with opacity with PropertyValuesHolder

We can define if we want the animations to affect the opacity; For example, if we want to indicate that the view goes from completely hidden to visible, we must use the ALPHA property with floating values between zero and one; the code in Kotlin would be:

PropertyValuesHolder.ofFloat(View.ALPHA, 0f, 1f))

Or if we want the transition to be from visible to hidden:

PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 0f))

Animating with the rotations with PropertyValuesHolder

To rotate the views we can do it in the X and/or Y axes through the ROTATION_X and ROTATION_Y properties respectively; to rotate in the X axis 45 degrees the code in Kotlin would be:

PropertyValuesHolder.ofFloat(View.ROTATION_X, 0f, 45f))

To rotate 45 degrees in the Y axis:

PropertyValuesHolder.ofFloat(View.ROTATION_Y, 0f, 45f))

In the previous example we indicated that we want to rotate from zero degrees to 45 degrees (it goes from 0 to 360 degrees).

In general, view rotations wouldn't be very useful unless you want to do something very specific.

Animating with scaling with PropertyValuesHolder

Another way to perform animations is with the scaling of the views in one of the X and Y axes whose values go from zero to completely hidden and to one for the original size, to scale in the X axis the code in Kotlin is as follows :

ObjectAnimator.ofPropertyValuesHolder(bottomLay,
       PropertyValuesHolder.ofFloat(View.SCALE_X,
               0f, 1f))

For the Y axis we use the SCALE_Y property.

Animating with translations with PropertyValuesHolder:

This view is very useful when we want to make the entrance or exit effect like the one in the image that we show at the beginning; for this, it is recommended that when it is output or input, use the total size of the view, that is, if the animation that we want to develop is the output animation on the Y axis, then it means that the view is being displayed (there is no translation, or the translation in the Y axis is zero) and the next state is the total concealment of the view; for this we must move the view to the bottom using the total size of the view to hide it below:

Hide Bottom animation

Based on what was explained above, we have:

PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0f, hi.toFloat())

Hide Top animation

We can play with the signs (positive and negative) to vary the translation from bottom to top or from top to bottom:

PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0f, -hi.toFloat())

Hide to the sides(right left) animation

Continuing with the translations in Android, to hide/show to the sides, that is, from right to left or left to right, we must use the View.TRANSLATION_X property instead of View.TRANSLATION_Y and instead of using the algo of the view, we use the width:

val wi = view.width

val iconAnim = ObjectAnimator.ofPropertyValuesHolder(view,
       PropertyValuesHolder.ofFloat(View.TRANSLATION_X, 0f, wi.toFloat()),

Finally, a base example code that we can adapt to any of the examples we saw previously would look like this with Kotlin:

val hi = view.height

view.visibility = View.VISIBLE
val iconAnim = ObjectAnimator.ofPropertyValuesHolder(view,
        PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, hi.toFloat(), 0f))
iconAnim.duration = VIEW_ANIMATION
iconAnim.start()

Multiple properties to perform more complex animation in Android

A very important point is that we can use one or more properties to perform the animations, that is, we can use one, two or three properties for the opacity, or an opacity and a translation or however we want to configure it; for this is the following code in Kotlin that shows how to perform a translation in the Y axis together with the opacity:

val hi = view.height

view.visibility = View.VISIBLE
val iconAnim = ObjectAnimator.ofPropertyValuesHolder(view,
        PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, hi.toFloat(), 0f),
        PropertyValuesHolder.ofFloat(View.ALPHA, 0f, 1f))
iconAnim.duration = VIEW_ANIMATION
iconAnim.start()

The code in Java would be as follows:

view.setVisibility(View.VISIBLE);
Animator iconAnim = ObjectAnimator.ofPropertyValuesHolder(view,
            PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0f, -
view.getHeight()),
            PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 0f));
iconAnim.setDuration(VIEW_ANIMATION);
iconAnim.start();

Java animations and methods/properties for time

With Java there is not much more to say, we see that it is a little more code, some methods are used instead of properties, but otherwise it is the same operation and same logic; and this is because both programming languages are very similar; At the end we have the setDuration() method in Java or the duration property in Kotlin, which allows us to define the time in milliseconds that the animation will last:

val VIEW_ANIMATION: Long = 300

And finally the start() method to start the animation; there is a startDelay method in Kotlin and in Java the setStartDelay() method to indicate the delay of the animation, this is very useful if we perform several animations at the same time.

Listener to control the states of animations

With the listener we can know when an animation starts, when it ends, if it is repeated or canceled and perform some action accordingly; For example, in the case of translations to hide the view by moving or translating the view either in the X or Y axis, it is a good advice to hide the view View.GONE once the animation is finished; for that we can use the onAnimationEnd method, in the same way, when the animation starts and the view is hidden, we can indicate in the onAnimationStart method that the view is visible again to start the animation View.VISIBLE; finally, the code in Kotlin would be:

iconAnim.addListener(object : Animator.AnimatorListener {

   override fun onAnimationStart(animation: Animator) {
   }

   override fun onAnimationEnd(animation: Animator) {
   }

   override fun onAnimationCancel(animation: Animator) {
   }

   override fun onAnimationRepeat(animation: Animator) {
   }
});

And in Java we have:

iconAnim.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
          bottomLay.setVisibility(View.VISIBLE);
    }
    @Override
    public void onAnimationEnd(Animator animation) {
    }
    @Override
    public void onAnimationCancel(Animator animation) {
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
    }
});

Where iconAnim is an instance of the ObjectAnimator class that we saw in the previous examples.

Types of animations in Android: Animations using Drawable

Another type of very common transition effects or animations are those used through Drawable resources that at the end define an XML with attributes and tags and are later attached to an element of the view to define the behavior of the animation.

Animations of views or resources (tween animation)

This type of animation allows you to vary the position, size, rotation and opacity/transparency of an element in a view; they are ideal to execute at the beginning of a screen or when the user performs some interaction on the content of the view, such as a click or something similar; they are also ideal for changing the status of elements of the views at the end of a process.

We can modify the following:

  • Duration How long will the animation last?
  • Delay
  • Time interpolation Properties that will change based on time.

Among some other properties, but these are the most important; finally, to obtain an animation like the one we see at the end of this section, we have to know the following information and thus understand how it works.

We use the following resource that we have registered in:

res/anim/animation.xml

The name animation.xml is the name of the resource, you can place whatever you want but it must be contained within res/anim/.

<set>: Parent container of the animation

A container containing the elements to animate (<alpha>, <alpha>, <scale>, <translate> and <rotate>) containing the following attributes:

  • android:interpolator It is the interpolation that we are going to apply in the animation.
  • android:shareInterpolator If true the same interpolation will be applied to all children of the element.
  • android:shareInterpolator If true the same interpolation will be applied to all children of the element.

<alpha>: Property for the opacity of animations

This is a property that allows defining the opacity value of the element in the animation, for that we have a couple of attributes:

  • android:fromAlpha is a float value ranging from 0.0 for fully invisible to 1.0 for fully visible; the mean value is transparent to may or less degree.
  • android:toAlpha is a float value that goes from 0.0 for fully visible to 1.0 for fully invisible; the mean value is transparent to may or less degree.

<scale>: Property for the scale of the animations

This powerful property allows resizing or resizing of the elements in the animation; for that, it uses a couple of pivots so that you can specify from where the rescaling of the pivotX and pivotY image will begin; For example, if the value taken by these pivots is 0, 0 respectively (top left of the element to animate) the animation will start from the top right to rescale; has the following attributes:

  • android:fromXScale: 1.0 means that the X axis will not be resized, another value indicates that the image is resized; is the value at which to start rescaling.
  • android:toXScale: 1.0 means that the X axis will not be rescaled, another value indicates that the image is resized; is the value at which the rescaling will stop.
  • android:fromYScale: 1.0 means that the Y axis will not be resized, another value indicates that the image is resized; is the value at which to start rescaling.
  • android:toYScale: 1.0 means that the Y axis will not be rescaled, another value indicates that the image is resized; is the value at which the rescaling will stop.
  • android:pivotX: Allows you to specify the X coordinate from where to start rescaling.
  • android:pivotY: Allows you to specify the Y coordinate from which to start rescaling.

<translate>: Property of animation translations

This property is also very useful, and allows translations between the X and Y axes, its operation is very similar to that of scaling, but with the focus on translations; the values go from -100 to 100 percent (that is, they are relative percentages to the same element to animate if the value is "%" and if the value is "%p" it indicates that the relative value is to the parent or container element of the element to animate); its attributes are:

 

  • android:fromXDelta: Value relative to the element to animate ("%") or to the parent element ("%p") indicates in percentages the initial translation on the X axis.
  • android:toXDelta: Value relative to the element to animate ("%") or to the parent element ("%p") indicates in percentages the final translation on the X axis.
  • android:fromYDelta: Value relative to the element to animate ("%") or to the parent element ("%p") indicates the initial translation in percentages on the Y axis.
  • android:toYDelta: Value relative to the element to animate ("%") or to the parent element ("%p") indicates in percentages the final translation on the Y axis.

<rotate> Property for animation rotations

Allows you to perform rotations; its attributes are:

 

  • android:fromDegrees: Float value indicating the starting position in degrees.
  • android:toDegrees: Float value indicating the final rotation in degrees.
  • android:pivotX: As with scaling, this value tells us the X position from where the rotation will be executed; It can be relative to the element to animate ("%") or to its parent ("%p")Y.
  • android:pivotY: As with scaling, this value tells us the Y position where the rotation will be executed; It can be relative to the element to animate ("%") or to its parent ("%p")Y.

Finally, with this clear, we present the following animation:

Animación de tipo recursos ejemplo

The resource we use is:

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="2000"
        android:fromXScale="3.0"
        android:fromYScale="2.0"
        android:toXScale="1.0"
        android:toYScale="1.0" />
    <rotate
        android:startOffset="2000"
        android:duration="2000"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"/>
    <translate
        android:startOffset="4000"
        android:duration="2000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="60"
        android:toYDelta="100" />
    <alpha
        android:startOffset="4000"
        android:duration="2000"
        android:fromAlpha="1"
        android:toAlpha="0" />
</set>

Then the code in Kotlin would be:

AnimationUtils.loadAnimation(this, R.anim.animacion).also {
	hyperspaceJumpAnimation ->
	findViewById<TextView>(R.id.text_view).startAnimation(hyperspaceJumpAnimation)
}

And in Java it would be:

ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);

Of course, you must replace the type of element and its name with yours that you want to animate.

Conclusion

In this post we saw how to make simple transitions or animations that are ideal for showing or hiding elements on a screen, but this goes much further, we still need to talk about how to make transitions between screens (clicking on a button shows the conversion of the button into the new screen), such as animating lists or the RecyclerView among many other things that we will see in future installments.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.