Jens Klingenberg

How to use StateListDrawable

Posted on February 4, 2018  •  2 minutes  • 333 words
Table of contents

What is a StateListDrawable?

Let’s say you have a View like a Button. You want to set a background to the button, you use
android:background=”@drawable/ic_assignment_returned_black_24dp”

But what can you do when you want to set a different background while the button is pressed or maybe when the button is not focused anymore.

My first solution for this problem was to extend a View class and override the setPressed() method to set the specific drawables.

class MyToggleButton : android.support.v7.widget.AppCompatButton {
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs,
defStyleAttr) {
}
override fun setPressed(pressed: Boolean) {
if (pressed) {
background = resources.getDrawable(R.drawable.ic_assignment_turned_in_black_24dp)
} else {
background = resources.getDrawable(R.drawable.ic_assignment_returned_black_24dp)
}
}
}

In the fragment where i used the button I then called the method inside a onTouchListener()

btn2.setOnTouchListener { v, event ->
  when {
    event.action == MotionEvent.ACTION_DOWN -> btn2.isPressed=true
    event.action == MotionEvent.ACTION_UP ->   btn2.isPressed=false
  }
  true
}

This process can be simplified with StateListDrawables.

How do they work?

You just create a new xml file e.g. button_selector.xml inside your drawables folder.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:drawable="@drawable/ic_assignment_turned_in_black_24dp" android:state_pressed="true"/>
<item  android:drawable="@drawable/ic_assignment_returned_black_24dp"/>
</selector>

This selector will do the same like my custom view. The drawable from the item with android:state_pressed=“true” will be used when the button is pressed. You can use StateListDrawables also for other attributes like textColor. Android will use the item without a state as the default one.

Here is a list of all states that are available:

android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_hovered=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_activated=["true" | "false"]
android:state_window_focused=["true" | "false"]

How to apply the selector?

You just use it like any other drawable inside your layout file
android:background="@drawable/button_selector"

Android will set the attributes when the view is in the specified state

And that’s it. Now you can apply this selector to any of your Views.

Example project and ressources

StateDrawableExample

Android Documentation StateList

Let's connect: