ImageButton Android avec un état sélectionné?

87

Si j'utilisais un ImageButton avec un sélecteur pour son arrière-plan, y a-t-il un état que je peux changer qui le fera changer d'apparence? À l'heure actuelle, je peux le faire changer d'images lorsqu'il est pressé, mais il ne semble y avoir aucun état "en surbrillance" ou "sélectionné" ou similaire qui me permet de changer son apparence à volonté.

Voici mon XML; il ne change d'apparence que lorsqu'il est pressé.

 <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" />

Joren
la source
1
Utiliser un ImageButton et suivre l'état sélectionné semble un peu un hack. Vous devez utiliser un bouton bascule, si vous souhaitez activer la fonctionnalité.
Andras Balázs Lajtha

Réponses:

214

Cela fonctionne pour moi:

<?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>

Et puis en 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
        }

    }

});

Pour une transition en douceur, vous pouvez également mentionner le temps d'animation:

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
Joshrl
la source
3
Cela a fonctionné pour moi, mais j'aimerais ajouter que l'on devrait créer ce xml dans votre dossier dessinable et si vous voulez que ImageButton soit mis en surbrillance lorsqu'il est pressé, vous devriez utiliser android: state_pressed plutôt que state_selected. De plus, cet état doit être au-dessus d'un élément sans état, car il est moins général.
Denis Kutlubaev
3
NOTE: order is important (the first matching state(s) is what is renderedcela a fonctionné mais étrange je n'ai pas compris POURQUOI?
Muhammad Babar
2
En l'absence d'attributs d'état, l'élément correspondra à n'importe quel état. Pensez donc au deuxième élément du sélecteur comme à l'état «catch all».
joshrl
2
La commande n'est pas importante, il vous suffit de vous assurer android:state_selected="false" de fournir celle par défaut!
Muhammad Babar
Comment puis-je faire la même chose dans un widget? J'ai un bouton mais je n'arrive pas à comprendre comment le faire.
Si8
19

ToggleImageButtonqui implémente l' Checkableinterface et prend en charge OnCheckedChangeListeneret l' android:checkedattribut xml:

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>
vokilam
la source
2
Comment puis-je l'utiliser? J'ai suivi les instructions dans: developer.android.com/training/custom-views/create-view.html mais je n'ai pas pu le faire fonctionner.
atisman
2
Merci! Notez qu'un sélecteur avec state_checkedne fonctionne pas avec cela cependant, vous devez utiliser state_selected.
Florian von Stosch
11

La meilleure façon de faire cela sans plus d'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;
        }
    });
}
András
la source
1
vous pouvez utiliser getResources (). getColor (R.color.lightblue) pour colorier à partir de votre xml.
Beto Caldas
@ András doit maintenir le bouton enfoncé un peu plus. Savez-vous pourquoi?
lionelmessi
3

Créez un fichier XML dans un res/drawabledossier. Par exemple, "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>

Vous pouvez combiner les fichiers que vous aimez, par exemple, changer "bg_state_1" en "bg_state_deselected" et "bg_state_2" en "bg_state_selected".

Dans n'importe lequel de ces fichiers, vous pouvez écrire quelque chose comme:

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

Créez dans un fichier de mise en page un ImageView ou ImageButton avec les attributs suivants:

<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"/>

Plus tard dans le code:

image.setSelected(!image.isSelected());
CoolMind
la source
2

Essaye ça:

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

Aussi pour les couleurs avec lesquelles j'ai eu du succès

<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>
Alex Volovoy
la source
Hmm. Cela ne semble pas aider. J'utilise un CompoundButton. Y a-t-il un état spécifique à ce type de bouton pour on \ off?
Joren
Oui, il est appelé vérifié voir isChecked () developer.android.com/reference/android/widget/…
Bostwickenator
0
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);
            }
MEGHA DOBARIYA
la source