Android ImageButton with a selected state?

AndroidButtonImagebutton

Android Problem Overview


If I was using an ImageButton with a selector for its background, is there a state I can change which will make it change its appearance? Right now I can get it to change images when pressed, but there seems to be no "highlighted" or "selected" or similar state which lets me toggle its appearance at will.

Here's my XML; it only changes appearance when pressed.

 <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:drawable="@drawable/map_toolbar_details" />

Android Solutions


Solution 1 - Android

This works for me:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- NOTE: order is important (the first matching state(s) is what is rendered) -->
    <item 
        android:state_selected="true" 
        android:drawable="@drawable/info_icon_solid_with_shadow" />
    <item 
        android:drawable="@drawable/info_icon_outline_with_shadow" />
 </selector>

And then in java:

//assign the image in code (or you can do this in your layout xml with the src attribute)
imageButton.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable....));

//set the click listener
imageButton.setOnClickListener(new OnClickListener() {

    public void onClick(View button) {
        //Set the button's appearance
        button.setSelected(!button.isSelected());

        if (button.isSelected()) {
            //Handle selected state change
        } else {
            //Handle de-select state change
        }
            
    }

});

For smooth transition you can also mention animation time:

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">

Solution 2 - Android

ToggleImageButton which implements Checkable interface and supports OnCheckedChangeListener and android:checked xml attribute:

public class ToggleImageButton extends ImageButton implements Checkable {
	private OnCheckedChangeListener onCheckedChangeListener;
	
	public ToggleImageButton(Context context) {
		super(context);
	}

	public ToggleImageButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		setChecked(attrs);
	}

	public ToggleImageButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		setChecked(attrs);
	}
	
	private void setChecked(AttributeSet attrs) {
		TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ToggleImageButton);
		setChecked(a.getBoolean(R.styleable.ToggleImageButton_android_checked, false));
		a.recycle();
	}

	@Override
	public boolean isChecked() {
		return isSelected();
	}

	@Override
	public void setChecked(boolean checked) {
		setSelected(checked);
		
		if (onCheckedChangeListener != null) {
			onCheckedChangeListener.onCheckedChanged(this, checked);
		}
	}

	@Override
	public void toggle() {
		setChecked(!isChecked());
	}

	@Override
	public boolean performClick() {
		toggle();
		return super.performClick();
	}
	
	public OnCheckedChangeListener getOnCheckedChangeListener() {
		return onCheckedChangeListener;
	}

	public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
		this.onCheckedChangeListener = onCheckedChangeListener;
	}

	public static interface OnCheckedChangeListener {
		public void onCheckedChanged(ToggleImageButton buttonView, boolean isChecked);
	}
}

res/values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ToggleImageButton">
        <attr name="android:checked" />
    </declare-styleable>
</resources>

Solution 3 - Android

The best way to do this without more images :

public static void buttonEffect(View button){
	button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

Solution 4 - Android

Create an XML-file in a res/drawable folder. For instance, "btn_image.xml":

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/bg_state_1"
          android:state_pressed="true"
          android:state_selected="true"/>
    <item android:drawable="@drawable/bg_state_2"
          android:state_pressed="true"
          android:state_selected="false"/>
    <item android:drawable="@drawable/bg_state_selected"
          android:state_selected="true"/>
    <item android:drawable="@drawable/bg_state_deselected"/>
</selector>

You can combine those files you like, for instance, change "bg_state_1" to "bg_state_deselected" and "bg_state_2" to "bg_state_selected".

In any of those files you can write something like:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#ccdd00"/>
    <corners android:radius="5dp"/>
</shape>

Create in a layout file an ImageView or ImageButton with the following attributes:

<ImageView
    android:id="@+id/image"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:adjustViewBounds="true"
    android:background="@drawable/btn_image"
    android:padding="10dp"
    android:scaleType="fitCenter"
    android:src="@drawable/star"/>

Later in code:

image.setSelected(!image.isSelected());

Solution 5 - Android

Try this:

 <item
   android:state_focused="true"
   android:state_enabled="true"
   android:drawable="@drawable/map_toolbar_details_selected" />

Also for colors i had success with

<selector
        xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:state_selected="true"
       
            android:color="@color/primary_color" />
        <item
            android:color="@color/secondary_color" />
</selector>

Solution 6 - Android

if (iv_new_pwd.isSelected()) {
                iv_new_pwd.setSelected(false);
                Log.d("mytag", "in case 1");
                edt_new_pwd.setInputType(InputType.TYPE_CLASS_TEXT);
            } else {
                Log.d("mytag", "in case 1");
                iv_new_pwd.setSelected(true);
                edt_new_pwd.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
            }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJorenView Question on Stackoverflow
Solution 1 - AndroidjoshrlView Answer on Stackoverflow
Solution 2 - AndroidvokilamView Answer on Stackoverflow
Solution 3 - AndroidAndrásView Answer on Stackoverflow
Solution 4 - AndroidCoolMindView Answer on Stackoverflow
Solution 5 - AndroidAlex VolovoyView Answer on Stackoverflow
Solution 6 - AndroidMEGHA DOBARIYAView Answer on Stackoverflow