Creating Custom Transition in Android

Kenny Hadisaputra
5 min readAug 22, 2020

Animation has been one of the core part of an Android application. It can gives more meaning and context to the user. It can also gives a sense of continuity between states or even pages.

As important as it is, it might be hard to make an animation in Android. Sometimes, all we want is just as simple as moving or fading a view. Android framework provides several ways to do something like that, but as an Android developer who is pretty much blind with this animation stuff, I try to find the easiest way possible without writing too much of this animation code myself.

Luckily, I found this video that explains how we can use Transition from Android to animate view easily from one state to another.

Transition is the process of changing from one state to another. In Android case, it is the process to animate in-between one view’s state to its other state (such as changing visibility).

Although the video explains how to use transition in a view-based application, it can still be applied to transition between activities or fragments by combining it with SharedElements.

Ok, after watching the video, I realised that I can now animate fading animation just by doing

TransitionManager.beginDelayedTransition(button.parent as ViewGroup, Fade(Fade.OUT))button.visibility = View.GONE

We just need to call TransitionManager.beginDelayedTransition , provide our transition, and then change the state of the view thereafter. The Fade transition is already provided by Android Transition library.

There are several common transition provided in the Transition library, such as Fade , Explode , and Slide .

One time, I got a task from the designer to animate view with a scale animation based on its visibility

Scale Animation Task

Believing that Scale is pretty common, I was pretty sure that the Transition library already provides a way for me to do that. But I couldn’t seem to find any Scale Transition in the library.

That means I have to make my own transition. And after looking at how the existing transition was made, I was surprised that it consists of Animator . So it means the Transition is just a wrapper of a defined beginning and end state, and then animation is run based on those states.

There are actually 2 ways to make a custom transition

  • Extends Transition abstract class
  • Extends Visibility abstract class

Transition abstract class provides full flexibility to create a new Transition. Visibility on the other hand, is a higher level abstract class that extends Transition and only works when the visibility of a view is changed (e.g. from View.VISIBLE to View.GONE).

Since what I need is to scale up when the visibility is visible and scale down when the visibility is gone, I just need to create a custom animation that extends Visibility .

There are some important functions that you need to override when you extends Visibility

  • captureStartValues is used to get current properties of the view. Since we want to make scale transition, we can try to get the current scale value of the view here.
  • onAppear function return the animation that we will use to animate when the view is turning visible. In my case, I have to return an animation from current scale value to 1.
  • onDisappear function return the animation that we will use to animate when the view is turning gone/invisible. In my case, I have to return an animation from current scale value to 0.

1. Capturing Start State

We will begin by capturing the start state. From the start state, we would like to know the current scale of our targeted view. This is necessary so that when the transition is somehow called multiple times in a really short time, we get the continuous animation because we always use the current scale position as our start point.

In the captureStartValues , we will need to store the current scale value in the transitionValues . transitionValues has property values that is like some kind of map and the key that we use to store our current scale value follows the naming scheme that google recommend here.

2. Create Visible Animator

After we capture the current scale value, we now have two states, as we know that the end state for when the view is in visible state will always be 1. So what we need to do is to create an animation for changing from the current scale value to 1.

The snippet is simply doing what we wanted to do. First, we need to get the current scale value that we store earlier in transitionValues . When somehow the value is null, we will default it to 0 (because we animate from View.GONE to View.VISIBLE).

Then we will create an Animator object to animate the scaling. Here, I use AnimatorSet which will play together two objectAnimators that animate scaling for each x and y axis.

Finally, I also put listener to the animator and also to the instance of the transition itself, so that when the animation or the transition ends we return the scale to 1 again.

This is necessary as we only need to change the scale value for the sake of animation. If you didn’t change the scale value back, the next time you wanted to change visibility of the view without transition, the view might not be in the size that you expected.

3. Create Gone Animator

After that, we just need to do the same for when the view is changed from View.VISIBLE to View.GONE . The difference from the previous one is that the end scale value is 0 instead of 1.

After doing that, our custom Scale transition is done.

Now, we can use our newly created transition like this

TransitionManager.beginDelayedTransition(button.parent as ViewGroup, Scale())button.visibility = View.GONE

The button will now animate itself scaling down before setting its visibility to View.GONE .

Tips: When you use the Transition in your project, there will be 2 suggestions on where to import from. One is from androidx.transition and one is from android.transition . Don’t forget to always choose androidx.transition if you have already migrated your project to AndroidX.



Kenny Hadisaputra

Android Developer and Kotlin Enthusiast (can also do a little bit iOS)