📜 ⬆️ ⬇️

Animations in Android on the shelves (Part 1. Basic animations)

Hello!

Today I want to tell a little about the animation in Android. I think for all quite obvious fact that animations can decorate our application. But I believe that they can do much more. The first is - good animations, even with modest graphics, can take our application to a completely new level. The second is an additional tool for communicating with the user, allowing you to focus attention, suggest application mechanics, and much more ... but this is a separate big topic.

Today we will talk about tools for creating animation. Unfortunately, it turned out that there are many ways to animate something in Android, and at first they are very easy to get confused. I will try to give the maximum general classification and leave links exclusively to the documentation, since tutorials can be found abound. I hope this article will help put everything in your head on the shelves and, if necessary, create an animation, choose the most appropriate way.

Part 1. Basic animations
Part 2. Complex animations
Part 3. "Low-level" animation
Part 4. Transition Animations
Part 5. Libraries for working with animation
')

Part 1. Basic animations


1. Frame by frame


image

I suppose that the first animation in the world was created this way, and this feature is still available in Android.

All you need to do is create an xml with links to each frame:

<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true"> <item android:drawable="@drawable/explosion_1" android:duration="15" /> <item android:drawable="@drawable/explosion_2" android:duration="15" /> <item android:drawable="@drawable/explosion_3" android:duration="15" /> ... </animation-list> 

And run the animation (hereinafter all the examples will be given at Kotlin):
 val animation = image.drawable as AnimationDrawable animation.start() 

• Application:

Difficult graphics animation, small size and prepared in an external editor.

• Advantages:

The ability to achieve any complexity effects

• Disadvantages:

Large consumption of resources and, as a result, rather expensive import into the application with the ability to get OutOfMemory. If for some reason you need to show a large number of frames, you will have to write your implementation with the gradual loading of images into memory. But if you had to do this, is it easier to resort to video?

2. Animating object properties (aka Property Animator)


image

If we only need to move something a few pixels to the side or change the transparency in order not to produce a million frames very similar to each other, Animator comes to the rescue. In fact, it can be used to animate any property of any objects.

The base abstract class is called Animator, it has several heirs, we are important:

ValueAnimator - allows you to animate any property
ObjectAnimator - inherited from ValueAnimator and has a simplified interface for animating View properties.
ViewPropertyAnimator - Provides another handy interface for animating View. Not inherited from Animator and used in the View :: animate () method

The animation above can be described as in the code:

 val animationX = ObjectAnimator.ofFloat(card, "scaleX", 1F) val animationY = ObjectAnimator.ofFloat(card, "scaleY", 1F) val set = AnimatorSet() set.play(animationX) .with(animationY) set.duration = DURATION set.interpolator = DecelerateInterpolator() set.start() 

so in XML ( animator/open_animator.xml ):

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:duration="250" android:propertyName="scaleX" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> <objectAnimator android:duration="250" android:propertyName="scaleY" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> </set> 

 val set = AnimatorInflater.loadAnimator(context, R.animator.open_animator) as AnimatorSet set.setTarget(card) set.start() 

It is also possible to describe our animation of transitions between States View, respectively, which will easily create animated transitions between States from any View. The animation described in the XML will automatically run when the View state changes.
animator/state_animator.xml

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true"> <set android:ordering="together"> <objectAnimator android:duration="250" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="scaleX" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:duration="250" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="scaleY" android:valueTo="1" android:valueType="floatType"/> </set> </item> <item android:state_enabled="false"> <set android:ordering="together"> <objectAnimator android:duration="250" android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="scaleX" android:valueTo="0" android:valueType="floatType"/> <objectAnimator android:duration="250" android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="scaleY" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector> 

 <View ... android:stateListAnimator="@animator/state_animator"> </View> 


• Application:

Animation of View objects and any of their parameters.
Animate any other options

• Advantages:

Absolutely Universal

• Disadvantages:

Somewhat resource demanding

3. Animation View (aka View animation)


Before the advent of Animator in Android, there were only Animations. The main disadvantage of which was that they animated only the view of the view and did not actually change its properties. Therefore, if you want to animate the movement of any element, then in addition to the end of the animation you need to change its properties. This approach is somehow not very convenient if you need a bit more complex animation or you need to catch clicks at the time of the animation.

Animation can be run as in code:

 val anim = ScaleAnimation(0F, 1F, 0F, 1F, 0F, card.measuredHeight.toFloat()) anim.duration = DURATION anim.interpolator = DecelerateInterpolator() anim.fillAfter = true card.startAnimation(anim) 

so in XML (note that the syntax is different from xml for Animator):
anim/open_animation.xml

 <?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="250" android:fillAfter="true" android:fromXScale="0" android:fromYScale="0" android:interpolator="@android:anim/decelerate_interpolator" android:pivotX="0" android:pivotY="100%" android:toXScale="1" android:toYScale="1"/> 

 val animation = AnimationUtils.loadAnimation(context, R.anim.open_animation) card.startAnimation(animation) 


• Application:

Where the API does not allow the use of Animator.

• Advantages:

Are missing

• Disadvantages:

Outdated API, changes only the view representation.

4. Animation of vector resources (aka AnimatedVectorDrawable)


image

In my opinion the most interesting part in Android animations. It is possible with relatively small forces to achieve complex and interesting effects. Transformations of icons in Android are made that way.

VectorDrawable consists of Path and Group elements. Creating an animation comes down to register movement to these elements. The Android in the picture above will look like this in the code:

Lot of code
drawable/hello_android.xml
 <?xml version="1.0" encoding="utf-8"?> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/enabled" android:drawable="@drawable/hello_android_enabled" android:state_enabled="true"/> <item android:id="@+id/disabled" android:drawable="@drawable/hello_android_disabled"/> <transition android:drawable="@drawable/hello_android_waving" android:fromId="@id/enabled" android:toId="@id/disabled"/> <transition android:drawable="@drawable/hello_android_stay_calm" android:fromId="@id/disabled" android:toId="@id/enabled"/> </animated-selector> 

drawable/hello_android_enabled.xml
 <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:rotation="-160" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector> 

drawable/hello_android_disabled.xml

 <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector> 

drawable/hello_android_waving.xml

 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector> </aapt:attr> <target android:name="group"> <aapt:attr name="android:animation"> <set> <objectAnimator android:propertyName="rotation" android:duration="300" android:valueFrom="0" android:valueTo="-170" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> <objectAnimator android:propertyName="rotation" android:startOffset="300" android:duration="200" android:valueFrom="-170" android:valueTo="-160" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> <objectAnimator android:propertyName="rotation" android:startOffset="500" android:duration="200" android:valueFrom="-160" android:valueTo="-170" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> <objectAnimator android:propertyName="rotation" android:startOffset="700" android:duration="200" android:valueFrom="-170" android:valueTo="-160" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> </set> </aapt:attr> </target> </animated-vector> 

drawable/hello_android_stay_calm.xml

 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="32dp" android:height="32dp" android:viewportHeight="32" android:viewportWidth="32"> <path android:fillColor="#000000" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z"/> <group android:name="arm" android:pivotX="20.5" android:pivotY="17" android:rotation="-160"> <path android:name="path" android:fillColor="#000" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16"/> </group> </vector> </aapt:attr> <target android:name="arm"> <aapt:attr name="android:animation"> <set> <objectAnimator android:duration="300" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="rotation" android:valueFrom="-160" android:valueTo="0" android:valueType="floatType"/> </set> </aapt:attr> </target> </animated-vector> 


In order not to write XML manually, you can use the online tool .

Starting from API 25, vector animations are rendered in RenderThread, so even if we load our UI Thread with something (but we never do that, right?), The animations will still play smoothly.

• Application:

Icons
Animation effects

• Advantages:

Performance

• Disadvantages:

There is no possibility to manually control the animation point in time (i.e., there is actually no method, like setCurrentTime)

All examples can be viewed and studied here .

Source: https://habr.com/ru/post/347918/


All Articles