'Get specific drawable from state list drawable
I have a state list drawable, and i want to get a specific drawable from the state list drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:kplus="http://schemas.android.com/apk/res-auto">
<item kplus:key_type_space_alt="true" android:state_pressed="true" android:drawable="@drawable/space_1_pressed" />
<item kplus:key_type_space_alt="true" android:drawable="@drawable/space_1_normal" />
<!-- TopNav keys. -->
<item kplus:key_type_topnav="true" android:state_pressed="true" android:drawable="@drawable/tab_down" />
<item kplus:key_type_topnav="true" android:state_selected="true" android:drawable="@drawable/tab_down" />
<item kplus:key_type_topnav="true" android:drawable="@drawable/tab_normal" />
<!-- TopRow keys. -->
<item kplus:key_type_toprow="true" android:state_pressed="true" android:drawable="@drawable/numeric_presseed" />
<item kplus:key_type_toprow="true" android:drawable="@drawable/numeric_normal" />
</selector>
I select the correct drawable state for each key, something like this:
if (keyIsNumbers) {
if (KPlusInputMethodService.sNumbersState == 2) {
drawableState = mDrawableStatesProvider.KEY_STATE_TOPNAV_CHECKED;
}
}
Now the states are defined like this:
KEY_STATE_TOPNAV_NORMAL = new int[] {keyTypeTopNavAttrId};
KEY_STATE_TOPNAV_PRESSED = new int[] {keyTypeTopNavAttrId, android.R.attr.state_pressed};
KEY_STATE_TOPNAV_CHECKED = new int[] {keyTypeTopNavAttrId, android.R.attr.state_selected};
Now my question is how to extract the correct drawable for each state ? I need to get the 9patch padding of the drawable, because if the state have different padding on 9patch it will get the padding only for the top drawable, and i want to set the padding manually for each key (drawable.getPadding(rect)).
Solution 1:[1]
There is no public API to get the drawable from the state.
There are some methods in StateListDrawable
but they are @hide
with the comment "pending API council".
You can invoke them by reflection... but it's at your own risk !!!. (it may change in future releases)
Those methods are :
Here is how to proceed (exceptions omitted) :
int[] currentState = view.getDrawableState();
StateListDrawable stateListDrawable = (StateListDrawable)view.getBackground();
Method getStateDrawableIndex = StateListDrawable.class.getMethod("getStateDrawableIndex", int[].class);
Method getStateDrawable = StateListDrawable.class.getMethod("getStateDrawable", int.class);
int index = (int) getStateDrawableIndex.invoke(stateListDrawable,currentState);
Drawable drawable = (Drawable) getStateDrawable.invoke(stateListDrawable,index);
Solution 2:[2]
now it is the way to get specific drawable without reflection:
StateListDrawable pressedDrawable = (StateListDrawable) this.mPressed;
final int state = android.R.attr.state_pressed;
final int index = pressedDrawable.findStateDrawableIndex(new int[]{state});
if (index >= 0) {
Drawable drawable = pressedDrawable.getStateDrawable(index);
if (drawable instanceof GradientDrawable) {
((GradientDrawable) drawable).setCornerRadius(mRoundConerRadius);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | VinceStyling |