Implementing Animations and Transitions in Android

Photo by Mado El Khouly on Unsplash

Android animations allow you to change the object behavior and property at runtime. It adds visual cues that notify your users about what is going on in the app. They are especially useful when the UI changes state, such as when new content loads or new actions become available. Animations also add a polished look to your app, which gives it a higher quality look and feel.

To better understand when to use animations, let’s take a look at how to use animations.
1. Informative: Motion designs help users to understand the relationships between elements, action availability and action outcomes.

2. Focused: Motions focuses attention on what is important, without unnecessarily creating distractions.

3. Expressive: Motion celebrates moments in user journeys, adds character to common interactions, and can express a brand’s style.

  1. Property Animation: This allows to animate almost anything. One can design an animation to change object’s property over a time, whether it is drawn to the screen or not. A property animation changes a property’s (a field in an object) value over a specified length of time. To animate something, you specify the object property that you want to animate, such as an object’s position on the screen, how long you want to animate it for, and what values you want to animate between.
  2. View Animations: This is used to perform simple animations like changing size, position, transparency and rotation. They are easy to be built and fast to run too. You don’t need a lot of code to write. If view animation accomplishes everything that you need to do, or if your existing code already works the way you want, there is no need to use the property animation system. It also might make sense to use both animation systems for different situations if the use case arises.
  3. Drawable Animations: This lets you load 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, played in order, like a roll of film.

Let’s go into each of the ways of creating animation one after the other for better understanding in their application.

Using Property Animation in android, we are going to create a sample project that uses property animation to create animation in android.

  1. Translation of View on Y axis

This is can be used in changing the TranslationY property of a view.

private void moveTextviewOnYaxis(){
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview, "translationY", 0,600);
objectAnimator.setDuration(2000)
.setInterpolator(new AnticipateOvershootInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

2. Translation of View on X axis

private void moveTextviewOnXaxis() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview, "translationX", 0, 600);
objectAnimator.setDuration(2000)
.setInterpolator(new AnticipateOvershootInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

3. Fading of the View

private void fadeTextview() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"alpha", 0, 1);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

4. Scaling of the View on the Y axis

private void scaleTextview() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"scaleY", 1, 20);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

5. Scaling of the View on the Xaxis

private void scaleTextview() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"scaleX", 1, 20);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

6. Rotation of the View

private void rotateTextView() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"rotation", 0, 90);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

7. Rotation of the View on the Y axis

private void rotateTextView() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"rotationY", 0, 90);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

8. Rotation of the View on the X axis

private void rotateTextView() {
isAnimationStarted = true;
objectAnimator = ObjectAnimator.ofFloat(firstTextview,
"rotationX", 0, 90);
objectAnimator.setDuration(2000)
.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(1);
objectAnimator.start();

}

9. Play Together two or more animations

private void combineAnimations() {
isAnimationStarted = true;
//Change the x pivot of a view
ObjectAnimator animX = ObjectAnimator.ofFloat(firstTextview,
"x", 50f);
animX.setDuration(2000)
.setInterpolator(new LinearInterpolator());
//Change the y pivot of a view
ObjectAnimator animY = ObjectAnimator.ofFloat(firstTextview,
"y", 100f);
animY.setDuration(2000)
.setInterpolator(new LinearInterpolator());
//Change the scale of a view
ObjectAnimator scaleAnim= ObjectAnimator.ofFloat(firstTextview,
"scaleY", 1, 20);
scaleAnim.setDuration(2000)
.setInterpolator(new LinearInterpolator());

//play the animations together
set = new AnimatorSet();
//use playSequentially if you want the animation to happen one after the other
set.playTogether(animX,animY,scaleAnim);
set.start();
}

10. Achieving Animation Combination with PropertyValueHolder

private void usingPropertyValueHolder() {
isAnimationStarted = true;
PropertyValuesHolder animX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder animY = PropertyValuesHolder.ofFloat("y", 100f);
PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 20);

ObjectAnimator.ofPropertyValuesHolder(firstTextview,animX, animY, scaleY).start();

}

Using XML To Create Animation

As above, we created animation using java, now we could create one using xml.

The animator set is loaded from xml using AnimatorInflater class. After loading the animator set, you need to set the target to the animator set before starting.

private void loadAnimatorFromXml(){
AnimatorSet animatorInflater = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(),R.animator.pivot_scale_animator);
animatorInflater.setTarget(firstTextview);
animatorInflater.start();
}

Using StateListAnimator, you can determine which animation to run when your view changes in state. For instance, when your view is focused or pressed or disabled, which animation you would like to run. Check below for example of this where we animate through when the state is pressed. The below xml name is scale_animate.xml

Setting the above state_animator xml to a view target by passing the scale_animate.xml to the android:stateListAnimator property.

Animate drawable graphics

One way to animate Drawables is to load 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, played in order, like a roll of film. The AnimationDrawable class is the basis for Drawable animations. Let’s see how to achieve this with an xml.

NB: you cannot start the animation in onCreate() of an activity because AnimationDrawable cannot be called in OnCreate() so if you wish the animation to kick off immediately then start the animation in onStart() since by then the views might be visible.

Use AnimatedVectorDrawable

Let’s create animated drawable using a vector drawables. First, you need to get vector drawable you want to animate. NB: Both paths must be compatible for morphing: they must have the same number of commands and the same number of parameters for each command. You can use this site to generate your animated vector drawable.

Using xml:

This is a bit complex, let’s take it one after the other for explanation. The root tag element should be <animated-vector/> and it requires drawable, which is the vector drawable.

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector_drawable">

<target
android:name="path"
android:animation="@animator/path_morph" />

</animated-vector>

a. The drawable points to the main vector drawable which is kept in the drawable resource folder. vector_drawable.xml

<vector
android:name="vector"
android:width="84dp"
android:height="84dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 20 11 L 7.83 11 L 13.42 5.41 L 12 4 L 4 12 L 12 20 L 13.41 18.59 L 7.83 13 L 20 13 L 20 11 Z"
android:fillColor="#000000"/>
</vector>

b. The animation points to the animation to be used for the path morphing. You can also create the objectAnimator animation file in the animator resource folder.

<objectAnimator
android:propertyName="pathData"
android:duration="350"
android:valueFrom="M 20 11 L 13.915 11 L 7.83 11 L 13.42 5.41 L 12 4 L 4 12 L 12 20 L 13.41 18.59 L 7.83 13 L 13.915 13 L 20 13 L 20 11 L 20 11"
android:valueTo="M 19 6.41 L 13.41 12 L 19 17.59 L 17.59 19 L 12 13.41 L 6.41 19 L 5 17.59 L 10.59 12 L 5 6.41 L 6.41 5 L 12 10.59 L 17.59 5 L 19 6.41"
android:valueType="pathType"/>

c. The target element in the animated-vector describes which animation run on a specified name.

After creating this animated vector drawable resource, you set it as a resource file to an imageview.

<ImageView
android:id="@+id/morph_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/avd_anim"
app:layout_constraintBottom_toTopOf="@id/blinking_stars"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

You can now reference the imageView in the java class.

ImageView morphImage = view.findViewById(R.id.morph_img);AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) morphImage.getDrawable();view.findViewById(R.id.animate_vecctor_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animatedVectorDrawable.start();
}
});

Animate layout changes to ViewGroup objects

Animations allows you to animate all kind of motions in your UI. Let’s first of all look at one easy way to do this before going into details. There is an auto animation that can handle layout changes in your ViewGroup. All you have to do is to enable animateLayoutChanges in your ViewGroup.

NB: Use the animateLayoutChanges in your immediate ViewGroup you want to animate the children views.

a. Auto animate Layout Updates.

This is using default layout transition so you can also use setLayoutTransition() to create a transition and if you want xml too, you can enable animateLayoutChanges as below.

<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
android:animateLayoutChanges="true" />

b. Using TransitionManager

When trying to alter the children view, for example, changing the position of the children views, changing the visibility of the children views and so on, you can easily call this beginDelayedTransition() to create the transitions.

TransitionManager.beginDelayedTransition(firstLay );view.setVisibility(isAnimationStarted? View.VISIBLE: View.GONE);

c. Using Transition to Change Layout in Same Screen.

We can use transition framework to change layouts through creating scene. Let’s create an example to get more understanding.

  1. Create main layout that holds the scenes we want to create.

Create the first layout to be used as a scene. Lets create first_scene.xml layout.

Create a second layout, this should be the layout that should be shown when doing the transition. The second layout should have same ids as the children views in the first layout for proper transition; if the ids become different from the first layout, the transition framework will use Fade transition to show the second scene. Create second layout, second_scene.xml.

2. Create starting scene from first layout and ending scene from second layout in java.

private void createScene(@NonNull View view) {
// Create the scene root for the scenes in this app
sceneRoot = view.findViewById(R.id.scene_root);

// Create the scenes
firstScene = Scene.getSceneForLayout(sceneRoot,R.layout.first_scene,getContext());
secondScene = Scene.getSceneForLayout(sceneRoot,R.layout.second_scene,getContext());
}

Create the transition you prefer for the change.

@NotNull
private TransitionSet getTransitionSet() {
final ChangeBounds changeBounds = new ChangeBounds();
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(changeBounds);
transitionSet.addTransition(new Fade());
return transitionSet;
}

Create a click listener to change between the first and the second scene.

transitionStarted = false;
view.findViewById(R.id.goBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
transitionStarted = !transitionStarted;

if (transitionStarted){
TransitionManager.go(secondScene,transitionSet);
}else {
TransitionManager.go(firstScene,transitionSet);
}

}
});

Now let’s put the java codes together.

We can implement transition in activity to activity interactions. Let’s look at how transitions in activity can be implemented.

a. Enabling the transition in the style.

<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>

b. Setting the Enter Transition: This is the transition that is used when the activity is entering into a scene and this can be done in the style resource too by

//this is setting the Enter transition in style resource
<item name=”android:windowEnterTransition” tools:targetApi=”lollipop”>@transition/slide_in</item>
//this is setting the Enter transition in Java
setEnterTransition(new Slide());

c. Setting the Exit Transition: This is used when the activity is leaving the current scene and it can also be set in the style resources by

//this is setting the Exit transition in style resource
<item name=”windowExitTransition” tools:targetApi=”lollipop”>@transition/slide_in</item>
//this is setting the Enter transition in Java
setExitTransition(new Slide());

This defines how views are shared between two activities. For example, when image exists in the two activities but with different position and size, we could use ChangeImageTransform transition to change the position and scale the image between the two activities.

a. Setting Shared Element Enter Transition: This can be set in the style resource.

// this is setting the Shared element enter transition in style resource
<item name="android:windowSharedElementEnterTransition" tools:targetApi="lollipop">@transition/change_image_transform</item>
//this is setting the Enter transition in Java
getWindow().setSharedElementEnterTransition(new ChangeTransform());

b. Setting Shared Element Exit Transition: This can be set in the style resource.

// this is setting the Shared element enter transition in style resource
<item name="android:windowSharedElementExitTransition" tools:targetApi="lollipop">@transition/change_image_transform</item>
//this is setting the Exit transition in Java
getWindow().setSharedElementExitTransition(new ChangeTransform());

Let us create an example showing how elements are shared in activity.

a. We need a start scene, so we create it now and you can name it as first_layout.xml containing only imageview and textview.

b. Reference the views in the java class. We link the second activity through a view click.

c. Create the destination activity which you can call SecondActivity.java with the same items views as were in the first activity but this time, going to be different size and position in order to see the transition happening.

In an activity to activity interaction, we can create a shared Element transition by creating activityOption object with a pair of the view from the first activity and the transitionName of the corresponding view in the second activity.

//Creating the activity options
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
Pair.<View, String>create(logo, getString(R.string.logo_transition)),
Pair.<View, String>create(textView, getString(R.string.text_transition)));
//passing the activity options to the startActivity method.
startActivity(new Intent(getContext(), SecondActivity.class), options.toBundle());

We can create Shared Element transition with fragments too. If you use normal FragmentManager to manage your fragment, then you can do below.

getSupportFragmentManager()
.beginTransaction()
.addSharedElement(view,transitionName) //adding the pair
.replace(R.id.content,YourFragment)
.commit();

If you are using navigation components library too, you can do this through the FragmentNavigator.Extras class as done below.

//using fragment in Navigation Component
HashMap<View, String> map = new HashMap<>();
map.put(logo, getString(R.string.frag_logo_transition));
map.put(textView, getString(R.string.frag_text_transition));

FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
.addSharedElements(map)
.build();
//Using Activity in Navigation Component
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
Pair.<View, String>create(logo,getString(R.string.frag_logo_transition)),
Pair.<View, String>create(textView,getString(R.string.frag_text_transition)));

ActivityNavigator.Extras extras1 = new ActivityNavigator.Extras.Builder()
.setActivityOptions(options)
.build();
//Navigating using NavController
navController.navigate(R.id.action_transitionFragment_to_secondFragment, null, null, extras);

In conclusion, using animation and transition in android application enhances the look and feel of the application and I think, it should not be too much as too much of everything becomes bad. 😉😉 You can find these examples in my github repository. Thanks for your time.

https://developer.android.com/training/basics/fragments/animate
https://developer.android.com/guide/topics/graphics/prop-animation

Senior Android Developer at ECOM Trading