androidandroid-custom-viewcustom-viewandroid-api-levelsstatelistdrawable

Get State Drawable from StateListDrawable for Custom View on Android API<29


How can I use StateListDrawable for my Custom View on Android before Q version (API<29)?

I have an XML StateListDrawable to enabled/disabled states

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:drawable="@drawable/seekbar_thumb_disable" />
    <item android:state_enabled="true" android:drawable="@drawable/seekbar_thumb_enable" />
</selector>

On Android Q and above (API>29), I can get the State Drawable like this:

final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyView, defStyle, 0);
StateListDrawable mStateListDrawable = (StateListDrawable) a.getDrawable(R.styleable.MyStateDrawable);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
    int index = mStateListDrawable.findStateDrawableIndex(new int[] { -android.R.attr.state_enabled});//for disabled
    mDrawable = mStateListDrawable.getStateDrawable(index);
}

But how can I do it for Android API<29?

The standard SeekBar View is able to get the State Drawable for its Thumb from the StateListDrawable on Android versions prior to API29. How?


Solution

  • For APIs below API 29, you can change the state for the StateListDrawable to each state that you are interested in and retrieve the current drawable.

    int[] savedState = mStateListDrawable.getState();
    mStateListDrawable.setState(new int[]{android.R.attr.state_enabled});
    Drawable drawableEnabled = mStateListDrawable.getCurrent();
    mStateListDrawable.setState(new int[]{~android.R.attr.state_enabled});
    Drawable drawableDisabled = mStateListDrawable.getCurrent();
    mStateListDrawable.setState(savedState);
    

    See the documentation for StateListDrawable.

    If you don't want to manipulate the original drawable, you can get a copy to manipulate as follows:

    StateListDrawable sld = (StateListDrawable) mStateListDrawable.getConstantState().newDrawable();