2010-04-09 28 views
73

Si estaba usando un ImageButton con un selector para su fondo, ¿hay algún estado que pueda cambiar que haga que cambie su apariencia? Ahora mismo puedo hacer que cambie las imágenes cuando las presiono, pero parece que no hay un estado "resaltado" o "seleccionado" o similar que me permita alternar su apariencia a voluntad.Android ImageButton con un estado seleccionado?

Aquí está mi XML; solo cambia de apariencia cuando se presiona.

<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

El uso de un ImageButton, y el seguimiento del estado seleccionado parece un poco un truco. Debería usar un botón para alternar, si desea alternar la funcionalidad. –

Respuesta

180

Esto funciona para mí:

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

Y luego, 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 
     } 

    } 

}); 

una transición suave también se puede hablar de tiempo de animación:

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

Esto funcionó para mí, pero me gustaría añadir, que uno debe crear este xml en su carpeta dibujable y si desea que ImageButton resalte cuando se presiona, debe usar android: state_pressed en lugar de state_selected. Además, este estado debe estar por encima de un elemento sin estado, ya que es menos general. – wzbozon

+2

'NOTA: el orden es importante (el primer estado coincidente es lo que se renderiza' Esto funcionó, pero extraño, no lo conseguí ¿POR QUÉ? –

+2

En ausencia de atributos de estado, el elemento coincidirá con cualquier estado. del segundo elemento en el selector como el estado "catch all." – joshrl

2

Prueba esto:

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

también para los colores que tuve éxito con

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

Hmm. No parece ayudar Estoy usando un CompoundButton. ¿Hay un estado específico para ese tipo de botón para encendido/apagado? – Joren

+0

Sí, se llama verificado, consulte _isChecked() _ http://developer.android.com/reference/android/widget/CompoundButton.html – Bostwickenator

9

La mejor manera de hacer esto sin más imágenes:

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

puedes usar getResources(). getColor (R.color.lightblue) para colorear desde tu xml –

+0

@ András necesita mantener el b utton presionó un poco más. ¿Sabes por qué es eso? – lionelmessi

+0

Puede usar sleep, pero no lo recomiendo ... –

15

ToggleImageButton cuales implementa la interfaz Checkable y admite OnCheckedChangeListener y android:checked xml atributo:

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/valores/attrs.xml:

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

Esta es la respuesta perfecta para mí. – Damir

+1

¿Cómo puedo usarlo? Seguí las instrucciones en: http://developer.android.com/training/custom-views/create-view.html pero no pude hacerlo funcionar. – atisman

+2

Gracias! Tenga en cuenta que un selector con 'state_checked' no funciona con esto, sin embargo, debe usar' state_selected'. –

1

Crear-archivo XML en una carpeta res/drawable. Por ejemplo, "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> 

Se pueden combinar esos archivos que te gusta, por ejemplo, el cambio "bg_state_1" a "bg_state_deselected" y "bg_state_2" a "bg_state_selected".

En cualquiera de esos archivos se puede escribir algo como:

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

Crear en un archivo de diseño de una ImageView o ImageButton con los siguientes 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"/> 

Más adelante en código:

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