ImageButton do Android com um estado selecionado?

87

Se eu estivesse usando um ImageButton com um seletor para seu plano de fundo, há um estado que posso alterar que fará com que ele mude sua aparência? Agora posso fazer com que ele mude as imagens quando pressionado, mas parece não haver nenhum estado "destacado" ou "selecionado" ou semelhante que me permita alternar sua aparência à vontade.

Aqui está meu XML; ele só muda de aparência quando pressionado.

 <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
fonte
1
Usar um ImageButton e rastrear o estado selecionado parece um pouco um hack. Você deve usar um botão de alternância, se desejar alternar a funcionalidade.
Andras Balázs Lajtha

Respostas:

214

Isso funciona para mim:

<?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 então em 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
        }

    }

});

Para uma transição suave, você também pode mencionar o tempo de animação:

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
Joshrl
fonte
3
Isso funcionou para mim, mas gostaria de acrescentar que deve-se criar este xml em sua pasta drawable e se você quiser que o ImageButton realce quando pressionado, você deve usar android: state_pressed em vez de state_selected. Além disso, este estado deve estar acima de um item sem estado, uma vez que é menos geral.
Denis Kutlubaev
3
NOTE: order is important (the first matching state(s) is what is renderedIsso funcionou, mas estranho, eu não entendi POR QUE?
Muhammad Babar
2
Na ausência de quaisquer atributos de estado, o item corresponderá a qualquer estado. Portanto, pense no segundo item no seletor como o estado "pega tudo".
joshrl
2
O pedido não é importante, você só precisa se certificar de fornecer android:state_selected="false" o padrão!
Muhammad Babar
Como posso fazer o mesmo em um widget? Eu tenho um botão, mas não consigo descobrir como fazê-lo.
Si8 de
19

ToggleImageButtonque implementa Checkableinterface e suportes OnCheckedChangeListenere android:checkedatributo 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
fonte
2
Como posso usar? Segui as instruções em: developer.android.com/training/custom-views/create-view.html, mas não consegui fazer funcionar.
atisman
2
Obrigado! Observe que um seletor com state_checkednão funciona com isso, você deve usar state_selected.
Florian von Stosch
11

A melhor maneira de fazer isso sem mais imagens:

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
fonte
1
você pode usar getResources (). getColor (R.color.lightblue) para colorir de seu xml.
Beto Caldas
@András precisa manter o botão pressionado um pouco mais. Você sabe por que isso?
lionelmessi
3

Crie um arquivo XML em uma res/drawablepasta. Por exemplo, "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>

Você pode combinar os arquivos que desejar, por exemplo, altere "bg_state_1" para "bg_state_deselected" e "bg_state_2" para "bg_state_selected".

Em qualquer um desses arquivos, você pode escrever algo como:

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

Crie em um arquivo de layout um ImageView ou ImageButton com os seguintes atributos:

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

Posteriormente no código:

image.setSelected(!image.isSelected());
CoolMind
fonte
2

Experimente isto:

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

Também para cores, tive sucesso com

<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
fonte
Hmm. Não parece ajudar. Estou usando um CompoundButton. Existe um estado específico para esse tipo de botão para ligar / desligar?
Joren,
Sim, é chamado de verificado, consulte 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
fonte