¿Cómo puedo dar un efecto de clic de vista de imagen como un botón en Android?

Tengo una vista de imagen en mi aplicación de Android que estoy usando como un botón con el evento onClick dado, pero como podría adivinar, no está dando a la vista de imagen un efecto de hacer clic cuando se hace clic. ¿Cómo puedo lograr eso?

Puede diseñar diferentes imágenes para estados cliqueados / no cliqueados y configurarlos en el OnTouchListener de la siguiente manera

final ImageView v = (ImageView) findViewById(R.id.button0); v.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent arg1) { switch (arg1.getAction()) { case MotionEvent.ACTION_DOWN: { v.setImageBitmap(res.getDrawable(R.drawable.img_down)); break; } case MotionEvent.ACTION_CANCEL:{ v.setImageBitmap(res.getDrawable(R.drawable.img_up)); break; } } return true; } }); 

La mejor opción es que defina un selector de la siguiente manera

     

y seleccione la imagen en el evento:

 v.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent arg1) { v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN); return true; } }); 

Puedes hacer esto con una sola imagen usando algo como esto:

  //get the image view ImageView imageView = (ImageView)findViewById(R.id.ImageView); //set the ontouch listener imageView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { ImageView view = (ImageView) v; //overlay is black with transparency of 0x77 (119) view.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP); view.invalidate(); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { ImageView view = (ImageView) v; //clear the overlay view.getDrawable().clearColorFilter(); view.invalidate(); break; } } return false; } }); 

Probablemente esté convirtiendo esto en una subclase de ImageView (o ImageButton, ya que también es una subclase de ImageView) para facilitar la reutilización, pero esto debería permitirle aplicar un aspecto “seleccionado” a una imagen.

Es posible hacerlo con solo un archivo de imagen usando el método ColorFilter. Sin embargo, ColorFilter espera trabajar con ImageViews y no con Buttons, por lo que debe transformar sus botones en ImageViews. Esto no es un problema si estás usando imágenes como botones de todos modos, pero es más molesto si tienes texto … De todos modos, suponiendo que encuentres una forma de resolver el problema con el texto, aquí está el código para usar:

 ImageView button = (ImageView) findViewById(R.id.button); button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY); 

Eso aplica una superposición roja al botón (el código de color es el código hexadecimal para el rojo totalmente opaco; los primeros dos dígitos son transparencia, luego es RR GG BB).

EDIT : aunque la respuesta original a continuación funciona y es fácil de configurar, consulte esta publicación de Android Developer Advocate en Google si desea / necesita una implementación más eficiente. También tenga en cuenta que el atributo android:foreground está llegando a todas las vistas , incluido ImageView, de forma predeterminada en Android M.


El problema con el uso de un selector para un ImageView es que solo puede establecerlo como fondo de la vista: siempre que su imagen sea opaca, no verá el efecto del selector detrás de ella.

El truco es envolver su ImageView en FrameLayout con el atributo android:foreground que nos permite definir una superposición para su contenido. Si establecemos android:foreground en un selector (por ejemplo, ?android:attr/selectableItemBackground OnClickListener Back para API nivel 11+) y OnClickListener a FrameLayout en lugar de ImageView, la imagen se superpondrá con el drawable de nuestro selector, el efecto de clic que deseamos !

Mirad:

    

(Tenga en cuenta que esto debe colocarse dentro de su diseño principal).

 final View imageButton = findViewById(R.id.imageButton); imageButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View view) { // do whatever we wish! } }); 

Use style = “? Android: borderlessButtonStyle” en el archivo XML. Mostrará el efecto de clic predeterminado de Android.

  

Simplemente usa un ImageButton .

Esta es mi manera simple de resolver eso:

 ImageView iv = (ImageView) findViewById(R.id.imageView); iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //Agrega porcentajes de cada fraccion de grafica pastel Animation animFadein = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_in); iv.startAnimation(animFadein); }); 

En el archivo res/anim/fade_in.xml :

 < ?xml version="1.0" encoding="utf-8"?>    

Establezca el fondo seleccionable en ImageView y agregue algo de relleno. A continuación, conecte OnClickListener .

  

Para definir la elección del selector seleccionable

     

Tengo que usar android: state_pressed en lugar de android: state_selected

     

Hago algunas cosas similares Ver adecuado para usted o no

Ver Press Effect Helper:

  • uso: hacer un efecto de prensa simple como iOS

    Uso simple:

  • ImageView img = (ImageView) findViewById (R.id.img);

  • ViewPressEffectHelper.attach (img)

https://gist.github.com/extralam/7489370

En combinación con todas las respuestas anteriores, quería presionar y cambiar el estado de ImageView, pero si el usuario se movía, entonces “canceló” y no realizó un onClickListener.

Terminé haciendo un objeto Point dentro de la clase y estableciendo sus coordenadas según el momento en que el usuario presionó hacia abajo el ImageView. En MotionEvent.ACTION_UP I grabando un nuevo punto y comparando los puntos.

Solo puedo explicarlo muy bien, pero esto es lo que hice.

 // set the ontouch listener weatherView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // Determine what action with a switch statement switch (event.getAction()) { // User presses down on the ImageView, record the original point // and set the color filter case MotionEvent.ACTION_DOWN: { ImageView view = (ImageView) v; // overlay is black with transparency of 0x77 (119) view.getDrawable().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP); view.invalidate(); p = new Point((int) event.getX(), (int) event.getY()); break; } // Once the user releases, record new point then compare the // difference, if within a certain range perform onCLick // and or otherwise clear the color filter case MotionEvent.ACTION_UP: { ImageView view = (ImageView) v; Point f = new Point((int) event.getX(), (int) event.getY()); if ((Math.abs(fx - px) < 15) && ((Math.abs(fx - px) < 15))) { view.performClick(); } // clear the overlay view.getDrawable().clearColorFilter(); view.invalidate(); break; } } return true; } }); 

Tengo un onClickListener en el imageView, pero este puede ser un método.

Puede setPressed en ImageView y realizar el filtrado de color allí, en lugar de crear detectores en TouchEvent:

 @Override public void setPressed(boolean pressed) { super.setPressed(pressed); if(getDrawable() == null) return; if(pressed) { getDrawable().setColorFilter(0x44000000, PorterDuff.Mode.SRC_ATOP); invalidate(); } else { getDrawable().clearColorFilter(); invalidate(); } } 

Puede probar con android:background="@android:drawable/list_selector_background" para obtener el mismo efecto que “Agregar alarma” en el “Reloj de alarma” predeterminado (ahora Reloj de escritorio).

Basado en la respuesta del Sr. Zorn , utilizo un método estático en mi clase de utilidad abstracta:

 public abstract class Utility { ... public static View.OnTouchListener imgPress(){ return imgPress(0x77eeddff); //DEFAULT color } public static View.OnTouchListener imgPress(final int color){ return new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: { ImageView view = (ImageView) v; view.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP); view.invalidate(); break; } case MotionEvent.ACTION_UP: v.performClick(); case MotionEvent.ACTION_CANCEL: { ImageView view = (ImageView) v; //Clear the overlay view.getDrawable().clearColorFilter(); view.invalidate(); break; } } return true; } }; } ... } 

Luego lo uso con onTouchListener:

 ImageView img=(ImageView) view.findViewById(R.id.image); img.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* Your click action */ } }); img_zc.setOnTouchListener(Utility.imgPress()); //Or Utility.imgPress(int_color_with_alpha) 

Es muy simple si tiene muchas imágenes y desea un efecto simple de toque, sin ningún XML dibujable y solo una imagen.

Use android.widget.Button y establezca su propiedad de background en android.graphics.drawable.StateListDrawable . Todo esto puede hacerse en XML o programáticamente. Consulte la sección Botón personalizado del tutorial de Form Stuff .

Esto funcionó para mí:

 img.setOnTouchListener(new OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { ((ImageView)v).setImageAlpha(200); break; } case MotionEvent.ACTION_MOVE: { // if inside bounds if(event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight()) { ((ImageView)v).setImageAlpha(200); } else { ((ImageView)v).setImageAlpha(255); } break; } case MotionEvent.ACTION_UP: { ((ImageView)v).setImageAlpha(255); } } return true; } }); 

@Editar: como Gunhan dijo que habrá un problema de compatibilidad con el método setImageAlpha. Usé este método:

 public static void setImageAlpha(ImageView img, int alpha) { if(Build.VERSION.SDK_INT > 15) { img.setImageAlpha(alpha); } else { img.setAlpha(alpha); } } 

Creo una muestra aquí , simplemente cambio ImageView en ClickableImageView desde su diseño. Espero que ayude

enter image description here

Tengo una solución más bella si usas imágenes de fondo 🙂

 public static void blackButton(View button){ button.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { v.getBackground().setColorFilter(0xf0f47521,PorterDuff.Mode.SRC_ATOP); v.invalidate(); break; } case MotionEvent.ACTION_UP: { v.getBackground().clearColorFilter(); v.invalidate(); break; } } return false; } }); } 

O:

Puede usar este formulario con el botón Imagen.

Crear archivo res/drawable/btn_video.xml :

 < ?xml version="1.0" encoding="utf-8"?>      

Y res/layout/activity_main.xml :

  

Su imagen cambia con un clic y puede ajustar con un diseño lineal:

 < ?xml version="1.0" encoding="utf-8"?>                  

Gracias por la ayuda en este hilo. Sin embargo, te perdiste una cosa … necesitas manejar el ACTION_CANCEL también. Si no lo hace, es posible que no restaure correctamente el valor alfa de ImageView en el caso de que una vista principal en la jerarquía de vista intercepte un evento táctil (piense en un ScrollView que le ajuste ImageView).

Aquí hay una clase completa que se basa en la clase anterior pero también se ocupa de ACTION_CANCEL. Utiliza una clase de ayuda de ImageViewCompat para abstraer las diferencias en la API previa de JellyBean.

 public class ChangeAlphaOnPressedTouchListener implements OnTouchListener { private final float pressedAlpha; public ChangeAlphaOnPressedTouchListener(float pressedAlpha) { this.pressedAlpha = pressedAlpha; } @Override public boolean onTouch(View v, MotionEvent event) { ImageView iv = (ImageView) v; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: ImageViewCompat.setAlpha(iv, pressedAlpha); break; case MotionEvent.ACTION_MOVE: if (isInsideViewBounds(v, event)) { ImageViewCompat.setAlpha(iv, pressedAlpha); } else { ImageViewCompat.setAlpha(iv, 1f); } break; case MotionEvent.ACTION_UP: ImageViewCompat.setAlpha(iv, 1f); break; case MotionEvent.ACTION_CANCEL: ImageViewCompat.setAlpha(iv, 1f); } return false; } private static boolean isInsideViewBounds(View v, MotionEvent event) { return event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight(); } } 

Aquí está mi código. La idea es que ImageView obtenga un filtro de color cuando el usuario lo toque, y el filtro de color se elimina cuando el usuario deja de tocarlo.

La solución de Martin Booka Weser, András, Ah Lam, altosh, no funciona cuando ImageView también tiene onClickEvent. La solución worawee.s y kcoppock (con ImageButton) requiere fondo, lo que no tiene sentido cuando ImageView no es transparente.

Esta es una extensión de la idea de AZ_ sobre el filtro de color.

 class PressedEffectStateListDrawable extends StateListDrawable { private int selectionColor; public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) { super(); this.selectionColor = selectionColor; addState(new int[] { android.R.attr.state_pressed }, drawable); addState(new int[] {}, drawable); } @Override protected boolean onStateChange(int[] states) { boolean isStatePressedInArray = false; for (int state : states) { if (state == android.R.attr.state_pressed) { isStatePressedInArray = true; } } if (isStatePressedInArray) { super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY); } else { super.clearColorFilter(); } return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } 

uso:

 Drawable drawable = new FastBitmapDrawable(bm); imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5)); 

Intenté con:

  

y esto funcionó. Tenga en cuenta en la línea: style="?android:borderlessButtonStyle"

Creo que la forma más fácil es crear un nuevo archivo XML. En este caso, vamos a llamarlo “example.xml” en la carpeta dibujable, e ingrese el siguiente código:

    

Pero antes tienes que establecer los colores en el archivo colors.xml, en la carpeta de valores, así:

  #0000FF  

Hecho eso, usted acaba de configurar el botón / ImageButton para usar el nuevo diseño, como este:

  

Luego, cuando haga clic en esa imagen, cambiará al color configurado en

  

dando los comentarios que quieras …

. Esta es la mejor solución que he visto. Es más genérico

  < ?xml version="1.0" encoding="utf-8"?>    

Aquí está mi solución, que, usando la biblioteca ” nineOldAndroids “, también admite API antiguas:

 rootView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(final View v, final MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: v.setBackgroundResource(R.drawable.listview_normal); ViewHelper.setAlpha(imageView, 1); break; case MotionEvent.ACTION_DOWN: v.setBackgroundResource(0); v.setBackgroundColor(getResources().getColor(R.color.listview_pressed)); ViewHelper.setAlpha(imageView, 0.75f); break; } return false; } }); 

Asume que la vista raíz es la propia celda (el diseño), y que tiene una sola vista de imagen que desea que se vea afectada por el color que desea aplicar a la celda completa.


EDITAR: si lo desea, también puede extender ImageView para manejar primer plano, y configurarlo en “? Android: attr / seleccionableItemBackground”. Aquí hay una biblioteca para esto y un tutorial sobre cómo hacerlo para cualquier vista que desee.

Si desea ondulación cuando se toca, se puede dar por este código:

  

Del mismo modo, puede implementar el efecto de clic para TextView

  

Solo agrega el atributo XML, android: clickable = “true” …

Por ahora, debemos desarrollar la práctica de Diseño de materiales . En este caso, podría agregar un efecto dominó en un ImageView.

Hice lo siguiente en XML: con 0 relleno alrededor de la imagen y ondulación ontop de la imagen: