2010-06-11 10 views
49

Tengo un ImageButton en mi aplicación y necesito cambiar el tinte de la imagen cuando el botón es pressed/focused. Tengo la ImageButton conjunto para obtener su src de un archivo XML, que de la siguiente manera:Cómo cambio el tinte de un ImageButton en el foco/presione

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <!-- pressed --> 
    <item 
     android:state_pressed="true" 
     android:tint="@color/black" 
     android:drawable="@drawable/search" 
     /> 

    <!-- focused --> 
    <item 
     android:state_focused="true" 
     android:tint="@color/black" 
     android:drawable="@drawable/search" 
     /> 

    <!-- default --> 
    <item 
     android:tint="@null" 
     android:drawable="@drawable/search" 
     /> 

</selector> 

Sin embargo, el tinte no se aplica cuando se presiona o se centró la ImageButton - la imagen sólo muestra como algo normal. El color negro se define como #000000 como siempre. ¿Algunas ideas?

+4

Hola. Me preguntaba si finalmente encontraste una forma XML de resolver esto. Gracias por adelantado. –

Respuesta

70

Puede cambiar el matiz, con bastante facilidad en el código a través de:

ImageButton button = (ImageButton) this.findViewById(R.id.button_i_want_to_modify); 
button.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint 

espero que ayude.

JS

+8

Trabajos. Pero me gustaría hacerlo a través de XML si es posible (lo siento exigente). –

+0

Compruebe la respuesta en http://stackoverflow.com/questions/19500039/how-to-use-selector-to-tint-imageview-in-android – asiby

+0

O utilice el enlace de datos. – ubuntudroid

-2

Como se ha definido el selector a ser el src de la ImageButton Android se acaba de tomar yo sepa el dibujable porque eso es lo que coincide con el tipo de Src. Entonces el tinte no se usará.

Sin embargo, tuve un problema similar: también traté de usar un selector como el suyo pero para el android: valor de tinte del ImageButton en lugar de android: src. Por supuesto, omití los valores de tinte que tienes en tu selector. Esto también resolvería su problema, porque desea usar el mismo dibujo para todos los estados. Curiosamente, obtengo una NumberFormatException cada vez que declaro que el sistema no pudo analizar 'res/color/tint_selector.xml' (que de hecho es mi selector) como un entero. Para ser más específicos mi código es el siguiente:

Ésta es mi selector, guardado en /res/color/tint_selector.xml:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" 
     android:color="#D3D3D3"/> <!-- pressed --> 
    <item android:color="#ff000000"/> <!-- default --> 
</selector> 

y este es el ImageButton correspondiente:

<ImageButton android:id="@+id/program_help" 
    android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:src="@drawable/symbol" 
    android:tint="@color/tint_selector"> 
</ImageButton> 

Tal vez esto te ayude un poco, aunque actualmente no funciona.

+0

¿Es esto compatible con API de menos de 21? – JHowzer

1

Lo que estoy haciendo es agregar un botón personalizado que tenga la función setColorFilter.

De esta manera puedo usar el nuevo botón en el xml.

public class CustomButton extends Button { 

public CustomButton(Context context) { 
    super(context); 
} 

public CustomButton(Context context, AttributeSet attributes) { 
    super(context, attributes); 
}; 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int maskedAction = event.getActionMasked(); 
    if (maskedAction == MotionEvent.ACTION_DOWN) 
     getBackground().setColorFilter(Color.argb(150, 155, 155, 155), PorterDuff.Mode.DST_IN); 
    else if (maskedAction == MotionEvent.ACTION_UP) 
     getBackground().setColorFilter(null); 
    return super.onTouchEvent(event); 
}} 

y para el ImageButton

public class CustomImageButton extends ImageButton { 

public CustomImageButton(Context context) { 
    super(context); 
} 

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

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int maskedAction = event.getActionMasked(); 
    if (maskedAction == MotionEvent.ACTION_DOWN) 
     setColorFilter(Color.argb(150, 155, 155, 155), PorterDuff.Mode.DST_IN); 
    else if (maskedAction == MotionEvent.ACTION_UP) 
     setColorFilter(null); 
    return super.onTouchEvent(event); 
}} 
1

me di cuenta de que hay algunas peticiones aquí para personas que quieren saber cómo hacer esto en XML. En realidad es bastante simple. Esto se puede lograr usando un layer-list

de su botón estirable (estirable/some_button.xml):

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" android:drawable="@drawable/some_button_highlighted" /> 
    <item android:drawable="@drawable/some_button_image" /> 
</selector> 

y este es el resaltado estirable (estirable/some_button_highlighted.xml)

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/some_button_image"/> 
    <item> 
     <shape> 
      <solid android:color="@color/highlighted_button_color" /> 
     </shape> 
    </item> 
</layer-list> 

Ahora puede usar esto en cualquier otro xml:

... 
android:drawable="@drawable/some_button" 
... 

Espero que esto ayuda a alguien en el futuro

+3

Esto simplemente dibuja un recuadro sólido sobre el dibujo, si hubiera una manera de hacer que la segunda capa use la capa anterior como una máscara alfa, entonces esto sería genial – darnmason

2
bt.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       switch (event.getAction()) { 
        case MotionEvent.ACTION_DOWN: 
         bt.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint 
         return true; // if you want to handle the touch event 
        case MotionEvent.ACTION_UP: 
         bt.clearColorFilter(); // White Tint 
         return true; // if you want to handle the touch event 
       } 
       return false; 
      } 
     }); 
5

fin he encontrar la solución para API < 21:

Button more = (Button) findViewById(R.id.more); 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    more.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN); 
} else { 
    Drawable wrapDrawable = DrawableCompat.wrap(more.getBackground()); 
    DrawableCompat.setTint(wrapDrawable, color)); 
    more.setBackgroundDrawable(DrawableCompat.unwrap(wrapDrawable)); 
} 

Que esto ayude a alguien no perder 2 horas!

+0

si está usando drawablecompat debería poder usarlo en versiones de API inferiores sin problema – dabluck

+0

Estaba usando un botón normal con un diseño XML personalizado. DrawableCompat fue la única solución actualizada que funciona en pre-API 21. –

4

Encontré una manera de hacer esto en xml (en la api 21 y al menos).

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" > 
     <bitmap 
      android:src="@drawable/search" 
      android:tint="@color/black" 
      /> 
    </item> 
    <item android:drawable="@drawable/search"/> 
</selector> 

Al establecer el matiz en el mapa de bits que es posible volver a utilizar el mismo estirable en XML sin tener que interceptar toques o subclase ImageView o ImageButton.

Una vez que se ha creado el selector, simplemente aplique eso como el src de ImageView o ImageButton.

+0

¡Buena captura! tenga en cuenta que el atributo de tinte en el elemento de mapa de bits antes de API 21 no hará nada -> https://code.google.com/p/android/issues/detail?id=78461 – Gomino

0

Puede establecer el color (tinte) desde xml.

Conjunto transparent (android:background="@null") para background a continuación, utilizar tint:

<ImageButton 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:tint="@color/Amber_200" 
    android:background="@null" 
    android:src="@drawable/back_selector" /> 
1

Aquí es cómo lo hizo utilizando sólo XML. En la carpeta dibujable crea un selector. Por ejemplo: touch_selector.xml

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 

    <!-- State when a row is being pressed, but hasn't yet been activated (finger down) --> 
    <item android:state_pressed="true" android:color="@color/semi_slate" /> 

    <!-- When the view is "activated". In SINGLE_CHOICE_MODE, it flags the active row 
    of a ListView --> 
    <item android:state_activated="true" android:color="@color/semi_slate" /> 

    <!-- Default, "just hangin' out" state. --> 
    <item android:color="@android:color/transparent" /> 
</selector> 

En mi punto de vista de la imagen en XML que establece el atributo android: matiz al dibujable creado anteriormente.

android:tint = "@drawable/touch_selector" 

Todo el código se veía así:

<?xml version="1.0" encoding="utf-8"?> 
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/poster" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:adjustViewBounds="true" 
android:scaleType="centerCrop" 
android:tint="@drawable/touch_selector" /> 

Esta es una solución todo XML, para poner el tinte en una ImageView en la prensa o en activo. Similar se puede hacer para ImageButton

Cuestiones relacionadas