Polishing UI in Android: StateListAnimator

Hello, Habr! On the eve of the start of the course “Android Developer. Professional “ we have prepared for you a translation of another interesting material.

We spend most of the development time for our Android application not working on the user interface – we just throw in a view and start writing code. I noticed that most of us don’t really care about the user interface. And I think this is fundamentally wrong. Mobile app developers have to take care of UI / UX as well. I am not saying “be an expert on mobile UI”, but you must understand the design language and its concepts.

I previously wrote an article on shadows in material design and received a lot of good reviews. I want to thank you all. “Mastering Shadows in Android” talks about elevation and shadow in Android. There I also showed how I supplemented my open source UI library with them. (Scaling Layout).

In this article, I want to improve my library with StateListAnimator and show you step by step how I will do it.


This article covers the following topics:

Drawable states

Android has 17 different states for Drawable.

We may have never even met some of them. I am not going to delve into every state. In most cases, we use pressed, enabled, windows focused, checked and so on. If we do not declare a state for a drawable, then it is assumed that this is the default state in Android.

We need to understand these states in order to write our own StateListDrawable


It is essentially a list of drawable items, where each item has its own state. To create the StateListDrawable, we need to create an XML file in the folder res/drawable

This is an item. It has two properties. Drawable and State


This is StateListDrawable. If we do not declare a state for an element, as I mentioned earlier, this means that it is default state

Can I use ShapeDrawable?

Yes. Instead of using android: drawable you can add any shape to your element. Here is an element with ShapeDrawable


You can use StateListDrawable from API level 1. Thus, there is no API level restriction for StateListDrawable.

That’s all. Now our view has a state. When the user clicks on it, its color will be changed. When the user releases it, it will have a default state and color.

But wait a second. Clickable? Why did we add this attribute? Do we also need to add it? Yes. But only for custom views. It takes time to find out. Buttons work fine without adding clickable because they are by default clickable… But if you want to use StateListDrawable for View, ImageView, Custom View, etc., you need to add the attribute clickable


I added StateListDrawable in this commit… It is similar to the example I gave above. When the user clicks on the layout, it is colored. But let’s improve this with StateListAnimator.


Remember that when you click the FloatingActionButton, its Z value increases due to animation. This is a StateListAnimator off-screen so to speak. Some material design widgets have their own StateListAnimator inside.

Let’s clear this up with a question on StackOverflow.

(How to remove border / shadow from lollipop buttons).

If Material Design widgets have their own StateListAnimator inside, we can set them to null to remove this function (not recommended, it was designed for a reason.) And now the answer sounds much more logical.

(Lollipop has a little nasty feature called stateListAnimatorwhich handles the height of the buttons, producing shadows.

Delete stateListAnimatorto get rid of shadows.

You have several options for how to do this:

In code:

button.setStateListAnimator (null);)

So how can we create it?

To understand StateListAnimator we need to understand property animation… I AM not going to dive deeper into animating properties in this article. But at least I want to show you the basics.

Animating properties

Here is the simplest example of a property in an object. X is a property.

class MyObject{
   private int x;
   public int getX() {
       return x;
   public void setX(int x) {
       this.x = x;

System property animation Is a robust framework that lets you animate almost all… You can define animation to change any property of an object over time, regardless of Togowhether it is displayed on the screen or not… A property animation changes the value of a property (a field in an object) over a specified period of time.

X is property… T – time… During animation, the X property is updated at the specified time. In general, this is how property animation works. Instead of a box, there can be a view or any object.

ValueAnimator Is the base class for animating properties. You can set up a listener to update the ValueAnimator and watch for property changes.

ObjectAnimator Is a class that inherits from ValueAnimator… You can use ObjectAnimator if the following are more suitable for you:

  • You have an object (any class with some property).
  • You don’t want to watch the ValueAnimator listener.
  • Do you want to update object property automatically.

So if we have view (which is an object) and we want to update the view property (x-coordinate, y-coordinate, rotation, translation or any other property that the view has a getter / setter for), we can use ObjectAnimator… Let’s continue creating the StateListAnimator.


The FAB button animates its “translationZ” property when pressed and released.

As I said earlier, we can use the object property directly without observing the changes in the animator. Each View has a translationZ property. This way we can directly animate translationZ using ObjectAnimator.

We can also combine several <objectAnimator>-ov in <set>... Let's change one more property View. Scale X and Scale Y...

Here's the result! It now also grows when clicked by the user. And here commit...

You can also define other properties in your animator.xml... You can find more information on using the ObjectAnimator here.

That's all. I am planning to write more about ValueAnimator and ObjectAnimator. This is a great API for animating an object.

Successful coding!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *