Home > database >  CustomButton on Android dev
CustomButton on Android dev

Time:10-12

I have been working on my game and I have tons of image buttons I would like to have some advice from you guys is there an alternative way to simplices button states since I would like to have that functionality where the appearance of buttons changes when user press it

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

just like this right now I have a lot of this in my project and hope there would be an alternative way my polluted drawable folder

CodePudding user response:

Instead of having a lot of drawable xml selectors you can create one custom ImageButton and create programmatically all the button states using the StateListDrawable. Example will be like the below:

First create your CustomButton which extends from AppCompatImageButton like the below:

public class CustomButton extends androidx.appcompat.widget.AppCompatImageButton {

    public CustomButton(@NonNull Context context) {
        super(context);
        init(context, null, 0);
    }

    public CustomButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public CustomButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr){

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomButton, defStyleAttr, 0);
        try {
            int defaultDrawableResId = typedArray.getResourceId(R.styleable.CustomButton_drawable_default, -1);
            int pressedDrawableResId = typedArray.getResourceId(R.styleable.CustomButton_drawable_pressed, -1);

            StateListDrawable stateListDrawable = new StateListDrawable();
            if(pressedDrawableResId!=-1) {
                stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, ContextCompat.getDrawable(context, pressedDrawableResId));
            }
            if(defaultDrawableResId!=-1) {
                stateListDrawable.addState(new int[]{}, ContextCompat.getDrawable(context, defaultDrawableResId));
            }
            setBackground(stateListDrawable);
        }
        catch (Exception e){
            Log.e("CustomButton", e.getMessage());
        }
        finally {
            typedArray.recycle();
        }
    }
}

Declare the CustomButton styleable under the res>values>attrs.xml like the below:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomButton">
        <attr name="drawable_default" format="reference" />
        <attr name="drawable_pressed" format="reference" />
    </declare-styleable>
</resources>

And then use this CustomButton in every layout needed by adding only the two states drawables (pressed|default) app:drawable_default and app:drawable_pressed like the below example layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.my.packagename.CustomButton
        android:layout_width="80dp"
        android:layout_height="80dp"
        app:drawable_default="@drawable/settings"
        app:drawable_pressed="@drawable/settings1"/>

</RelativeLayout>

This will eliminate all your xml drawable selectors and gives you also the ability to reuse any UI and any logic used inside the CustomButton.

  • Related