android - How to add a custom button state -
for instance, default button has following dependencies between states , background images:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_default_normal" /> <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/btn_default_normal_disable" /> <item android:state_pressed="true" android:drawable="@drawable/btn_default_pressed" /> <item android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_default_selected" /> <item android:state_enabled="true" android:drawable="@drawable/btn_default_normal" /> <item android:state_focused="true" android:drawable="@drawable/btn_default_normal_disable_focused" /> <item android:drawable="@drawable/btn_default_normal_disable" /> </selector>
how can define own custom state (smth android:state_custom
), use dynamically change button visual appearance?
the solution indicated @(ted hopp) works, needs little correction: in selector, item states need "app:" prefix, otherwise inflater won't recognise namespace correctly, , fail silently; @ least happens me.
allow me report here whole solution, more details:
first, create file "res/values/attrs.xml":
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="food"> <attr name="state_fried" format="boolean" /> <attr name="state_baked" format="boolean" /> </declare-styleable> </resources>
then define custom class. instance, may class "foodbutton", derived class "button". have implement constructor; implement one, seems 1 used inflater:
public foodbutton(context context, attributeset attrs) { super(context, attrs); }
on top of derived class:
private static final int[] state_fried = {r.attr.state_fried}; private static final int[] state_baked = {r.attr.state_baked};
also, state variables:
private boolean misfried = false; private boolean misbaked = false;
and couple of setters:
public void setfried(boolean isfried) {misfried = isfried;} public void setbaked(boolean isbaked) {misbaked = isbaked;}
then override function "oncreatedrawablestate":
@override protected int[] oncreatedrawablestate(int extraspace) { final int[] drawablestate = super.oncreatedrawablestate(extraspace + 2); if (misfried) { mergedrawablestates(drawablestate, state_fried); } if (misbaked) { mergedrawablestates(drawablestate, state_baked); } return drawablestate; }
finally, delicate piece of puzzle; selector defining statelistdrawable use background widget. file "res/drawable/food_button.xml":
<?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/com.mydomain.mypackage"> <item app:state_baked="true" app:state_fried="false" android:drawable="@drawable/item_baked" /> <item app:state_baked="false" app:state_fried="true" android:drawable="@drawable/item_fried" /> <item app:state_baked="true" app:state_fried="true" android:drawable="@drawable/item_overcooked" /> <item app:state_baked="false" app:state_fried="false" android:drawable="@drawable/item_raw" /> </selector>
notice "app:" prefix, whereas standard android states have used prefix "android:". xml namespace crucial correct interpretation inflater , depends on type of project in adding attributes. if application, replace com.mydomain.mypackage actual package name of application (application name excluded). if library must use "http://schemas.android.com/apk/res-auto" (and using tools r17 or later) or runtime errors.
a couple of notes:
it seems don't need call "refreshdrawablestate" function, @ least solution works is, in case
in order use custom class in layout xml file, have specify qualified name (e.g. com.mydomain.mypackage.foodbutton)
you can weel mix-up standard states (e.g. android:pressed, android:enabled, android:selected) custom states, in order represent more complicated state combinations
Comments
Post a Comment