Android ImageButton con uno stato selezionato?


87

Se stavo usando un ImageButton con un selettore per il suo sfondo, c'è uno stato che posso cambiare che gli farà cambiare aspetto? In questo momento posso fare in modo che cambi immagini quando viene premuto, ma sembra che non ci sia uno stato "evidenziato" o "selezionato" o simile che mi consenta di alternarne l'aspetto a piacimento.

Ecco il mio XML; cambia aspetto solo quando viene premuto.

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


1
Usare un ImageButton e tenere traccia dello stato selezionato sembra un po 'un trucco. È necessario utilizzare un pulsante di attivazione / disattivazione, se si desidera attivare / disattivare la funzionalità.
Andras Balázs Lajtha

Risposte:


214

Questo funziona per 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>

E poi 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
        }

    }

});

Per una transizione fluida puoi anche menzionare il tempo di animazione:

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

3
Questo ha funzionato per me, ma vorrei aggiungere che dovresti creare questo xml nella tua cartella disegnabile e se vuoi che ImageButton evidenzi quando viene premuto, dovresti usare android: state_pressed invece di state_selected. Inoltre, questo stato dovrebbe essere al di sopra di un elemento senza stato, poiché è meno generale.
Denis Kutlubaev

3
NOTE: order is important (the first matching state(s) is what is renderedquesto ha funzionato ma strano non ho capito PERCHÉ?
Muhammad Babar

2
In assenza di attributi di stato, l'elemento corrisponderà a qualsiasi stato. Quindi pensa al secondo elemento nel selettore come allo stato "cattura tutto".
joshrl

2
L'ordine non è importante, devi solo assicurarti di fornire android:state_selected="false" quello predefinito!
Muhammad Babar

Come posso fare lo stesso in un widget? Ho un pulsante ma non riesco a capire come farlo.
Si8

19

ToggleImageButtonche implementa l' Checkableinterfaccia, i supporti OnCheckedChangeListenere l' android:checkedattributo 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>

2
Come posso usarlo? Ho seguito le istruzioni in: developer.android.com/training/custom-views/create-view.html ma non sono riuscito a farlo funzionare.
atisman

2
Grazie! Nota che un selettore con state_checkednon funziona con questo però, devi usare state_selected.
Florian von Stosch

11

Il modo migliore per farlo senza più immagini:

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;
        }
    });
}

1
puoi usare getResources (). getColor (R.color.lightblue) per colorare dal tuo xml.
Beto Caldas

@ András deve tenere premuto il pulsante ancora un po '. Sai perché è così?
lionelmessi

3

Crea un file XML in una res/drawablecartella. Ad esempio, "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>

Puoi combinare i file che ti piacciono, ad esempio, cambiare "bg_state_1" in "bg_state_deselected" e "bg_state_2" in "bg_state_selected".

In uno qualsiasi di questi file puoi scrivere qualcosa come:

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

Crea in un file di layout un ImageView o ImageButton con i seguenti attributi:

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

Più avanti nel codice:

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

2

Prova questo:

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

Anche per i colori con cui ho avuto successo

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

Hmm. Non sembra aiutare. Sto usando un CompoundButton. Esiste uno stato specifico per quel tipo di pulsante per accensione / spegnimento?
Joren

Sì, si chiama controllato vedi 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);
            }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.