2012-06-19 12 views
35

Tengo una vista de imagen en la que he establecido un mapa de bits recuperado de una url. En la vista de imagen he configurado un OnClickListener que abre un cuadro de diálogo.Imagen de Android cambio de matiz para simular el botón haga clic en

Quiero de alguna manera cambiar el tinte (hacerlo más oscuro) cuando se presiona la vista de la imagen para proporcionar una especie de clic de botón como sensación.

¿Qué es lo que sugiere?

Respuesta

0

Tendría que probarlo, pero debería poder establecer un xml con ese comportamiento como Drawable de ImageView y luego establecer su mapa de bits como el fondo de ImageView.

6

Una forma sería usar una combinación de ColorFilter y ColorStateList que contenga el color del tinte para cuando se presiona el botón. El XML para el ColorStateList en el directorio res/de color se vería así:

button_pressed.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="@color/pressed_color"/> 
    <item android:color="#00000000"/> 

</selector> 

donde @color/pressed_color es su color de la tinta (que debe ser parcialmente transparente). Luego, en su subclase ImageView, aplique el color anulando drawableStateChanged().

@Override 
protected void drawableStateChanged() { 
    super.drawableStateChanged(); 

    ColorStateList list = getResources().getColorStateList(R.color.button_pressed); 
    int color = list.getColorForState(getDrawableState(), Color.TRANSPARENT); 
    setColorFilter(color); 
    invalidate(); 
} 

Cada vez que cambia el estado del botón, se llama a este código y configurará automáticamente el tinte según corresponda.

+0

I probé tu sugerencia No parece hacer nada. Utilizando el depurador noté que el método drawableStateChanged() no se activa en onPress, sino que parece activarse solo en onClick. – Abhishek

+0

Hmm, no puedo ver ningún error en el código anterior. Por definición, el método debe invocarse cuando el estado presionado cambia. He estado usando esta construcción en mi propio código y funciona bien. Como prueba, en su XML de ImageView agregue 'android: tint =" @ color/pressed_color "'. Esto debería agregar un tinte permanente a su imagen, ya que llama al mismo método de configuración del filtro de color que el código anterior. De esta forma, al menos puedes descartar un problema con el color que elijas. – happydude

+0

Lo siento, soy tonto. Puede simplemente agregar su lista de estado de color directamente a su archivo XML 'ImageView' directamente. Ver editar arriba. – happydude

0

Para mí, una solución simple es trabajar, utilizando setAlpha (180) en onClick caso que la imagen sea más oscura, dando al usuario una retroalimentación que se ha hecho clic o tocado.

final ImageView myImage = (ImageView) findViewById(R.id.ivDocument); 
myImage.setImage...(... your image ...); // load your ImageView 
myImage.setClickable(true); 
myImage.setFocusable(true); 
myImage.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     myImage.setAlpha(180); 
     doWhateverYouWantHere(v); 
    } 
}); 

En cuanto a su diseño XML, nada especial.

88

La respuesta de happydude es la forma más elegante de manejar esto, pero desafortunadamente (como se señala en los comentarios), el código fuente de ImageView solo acepta un número entero (color sólido). Issue 18220 ha sido de alrededor de un par de años frente a esto, he publicado una solución que no voy a resumir aquí:

Extender ImageView y envolver drawableStateChanged() con código que establece el matiz basado en el nuevo estado:

TintableImageView.java

package com.example.widgets; 

import android.content.Context; 
import android.content.res.ColorStateList; 
import android.content.res.TypedArray; 
import android.util.AttributeSet; 
import android.support.v7.widget.AppCompatImageView; 

import com.example.R; 

public class TintableImageView extends AppCompatImageView { 

    private ColorStateList tint; 

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

    public TintableImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context, attrs, 0); 
    } 

    public TintableImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context, attrs, defStyle); 
    } 

    private void init(Context context, AttributeSet attrs, int defStyle) { 
     TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0); 
     tint = a.getColorStateList(R.styleable.TintableImageView_tintColorStateList); 
     a.recycle(); 
    } 

    @Override 
    protected void drawableStateChanged() { 
     super.drawableStateChanged(); 
     if (tint != null && tint.isStateful()) 
      updateTintColor(); 
    }  

    private void updateTintColor() { 
     int color = tint.getColorForState(getDrawableState(), 0); 
     setColorFilter(color); 
    } 

} 

definir un atributo personalizado:

attrs.xml

<?xml version="1.0" encoding="UTF-8"?> 
<resources> 

    <declare-styleable name="TintableImageView"> 
     <attr name="tintColorStateList" format="reference|color" /> 
    </declare-styleable> 

</resources> 

utilizar el widget y el atributo personalizado con su espacio de nombres local en lugar de Android de:

example_layout.xml

<?xml version="1.0" encoding="UTF-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal"> 

    <com.example.widgets.TintableImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@drawable/example" 
     android:clickable="true" 
     app:tintColorStateList="@color/color_selector"/> 

</LinearLayout> 

continuación, puede utilizar un selector de color como happydude sugirió:

color_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="@color/pressed_color"/> 
    <item android:color="#00000000"/> 
</selector> 
+2

Estoy intentando su solución, pero aún obtengo 'java.lang.NumberFormatException: Invalid int:" @ 2130837701 "' cuando un constructor dentro de 'TintableImageView' llama a su super ... Necesitaba pasar' new int [] {R .styleable.TintableImageView_tint} 'porque' obtainStyledAttributes' pedía una matriz y declaraba ' @ drawable/tab_icon_selector' dentro de colors.xml para poder hacer referencia a ella desde android: tint –

+3

Es por eso que mi respuesta define un atributo de tinte personalizado en attrs.xml. Debes utilizar la aplicación ** personalizada: tinte ** en tu diseño en lugar de ** android: tint **. Esencialmente, está creando un nuevo atributo que envuelve el nativo y lo alimenta de un color a la vez. –

+0

¡gracias por responder! Cambié a 'app: tint' y la excepción desapareció ... Pero el selector todavía no se usa, es decir, mis iconos son negros todo el tiempo ... es mi declaración dibujable dentro de colors.xml de la manera correcta ¿para hacerlo? –

-1

Este fragmento de código que funcionó para mí:

porterDuffColorFilter = newPorterDuffColorFilter(getResources().getColor(R.color.cardview_dark_background),PorterDuff.Mode.MULTIPLY); 

imgView.getDrawable().setColorFilter(porterDuffColorFilter); 
imgView.setBackgroundColor(Color.TRANSPARENT); 
Cuestiones relacionadas