Puede diseñar diferentes imágenes para estados en los que se hizo clic o en los que no se hizo clic y configurarlas en 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 definir un selector de la siguiente manera
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@drawable/img_down" />
<item android:state_selected="false"
android:drawable="@drawable/img_up" />
</selector>
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;
}
});
MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVE
mantener la imagen visible mientras estemos presionando.setOnTouchListener(...
. Simplemente puede crear el<selector ...>
y luego configurar el ImageView en el que se puede hacer clic en XML como<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
Puede 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 convertiré esto en una subclase de ImageView (o ImageButton, ya que también es una subclase de ImageView) para facilitar su reutilización, pero esto debería permitirle aplicar un aspecto "seleccionado" a una vista de imagen.
fuente
false
, de lo contrario, elonClick()
evento real de la vista no se activaráEs posible hacerlo con un solo 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á usando imágenes como sus botones de todos modos, pero es más molesto si tiene texto ... De todos modos, suponiendo que encuentre una forma de solucionar el problema con el texto, aquí está el código que debe 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 completamente opaco; los primeros dos dígitos son transparencia, luego es RR GG BB).
fuente
EDITAR : Aunque la respuesta original a continuación funciona y es fácil de configurar, consulte esta publicación de un Defensor de desarrolladores de Android en Google si desea / necesita una implementación más eficiente. También tenga en cuenta que el
android:foreground
atributo llega 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 configurarlo como fondo de la vista; siempre que su imagen sea opaca, no verá el efecto del selector detrás de ella.
El truco consiste en envolver su ImageView en un FrameLayout con el atributo
android:foreground
que nos permite definir una superposición para su contenido. Si configuramosandroid:foreground
un selector (por ejemplo,?android:attr/selectableItemBackground
para el nivel de API 11+) y adjuntamos elOnClickListener
FrameLayout en lugar de ImageView, la imagen se superpondrá con el dibujable de nuestro selector: ¡el efecto de clic que deseamos!Mirad:
<FrameLayout android:id="@+id/imageButton" android:layout_width="match_parent" android:layout_height="match_parent" android:foreground="?android:attr/selectableItemBackground" > <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/yourImageFile" /> </FrameLayout>
(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! } });
fuente
selectableItemBackground
atributo solo se agregó en el nivel de API 11, por lo que debe usar otro selector si desea usar esta solución para niveles de API anteriores. Por ejemplo, para una de mis aplicaciones que admite API nivel 7, uso el@drawable/list_selector_holo_light
recurso generado con la herramienta Android Holo Colors Generator .<ImageButton>
con selectableItemBackground!Utilice style = "? Android: borderlessButtonStyle" en el archivo XML. Mostrará el efecto de clic predeterminado de Android.
<ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" style="?android:borderlessButtonStyle" />
fuente
android:adjustViewBounds="true"
para desarmar el relleno.style="?android:attr/borderlessButtonStyle"
: developer.android.com/guide/topics/ui/controls/…Simplemente use un ImageButton .
fuente
Aquí está mi forma sencilla 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 archivo
res/anim/fade_in.xml
:<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" > <alpha android:duration="100" android:fromAlpha="0.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="1.0" /> </set>
fuente
Establezca el fondo seleccionable en ImageView y agregue algo de relleno. Luego adjunte el
OnClickListener
.<ImageView android:id="@+id/your_image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/your_image" android:padding="10dp" android:background="?android:attr/selectableItemBackground"/>
fuente
Para definir la opción dibujable del selector
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:drawable="@drawable/img_down" /> <item android:state_selected="false" android:drawable="@drawable/img_up" /> </selector>
Tengo que usar android: state_pressed en lugar de android: state_selected
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed ="true" android:drawable="@drawable/img_down" /> <item android:state_pressed ="false" android:drawable="@drawable/img_up" /> </selector>
fuente
Puede intentar
android:background="@android:drawable/list_selector_background"
obtener el mismo efecto que "Agregar alarma" en el "Reloj despertador" predeterminado (ahora Reloj de escritorio).fuente
Si desea ondulación cuando se toca, se puede dar con este código:
<ImageView ... android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" ... </ImageView>
Del mismo modo, puede implementar el efecto de clic para TextView
<TextView ... android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" ... </TextView>
fuente
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 dijo Gunhan, 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); } }
fuente
Hago algunas cosas similares. Veo conveniente para ti o no.
Ver Asistente de efectos de prensa:
uso: haz un simple efecto de prensa como iOS
Uso simple:
ImageView img = (ImageView) findViewById (R.id.img);
https://gist.github.com/extralam/7489370
fuente
En combinación con todas las respuestas anteriores, quería presionar ImageView y cambiar de estado, pero si el usuario se movía, entonces "cancela" y no realiza un onClickListener.
Terminé haciendo un objeto Point dentro de la clase y estableciendo sus coordenadas de acuerdo con el momento en que el usuario presionó el ImageView. En MotionEvent.ACTION_UP grabé un nuevo punto y comparé 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(f.x - p.x) < 15) && ((Math.abs(f.x - p.x) < 15))) { view.performClick(); } // clear the overlay view.getDrawable().clearColorFilter(); view.invalidate(); break; } } return true; } });
Tengo un onClickListener configurado en imageView, pero esto puede ser un método.
fuente
MotionEvent.ACTION_CANCEL
con la misma funcionalidad queMotionEvent.ACTION_UP
entonces es posible "borrar" la vista si los usuarios realizan un "arrastre" que no es una acción de clic.Puede anular
setPressed
en ImageView y hacer el filtrado de color allí, en lugar de crear oyentes onTouchEvent:@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(); } }
fuente
Según 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 onTouch simple, sin ningún elemento de diseño XML y solo una imagen.
fuente
Utilice an
android.widget.Button
, y establezca subackground
propiedad en anandroid.graphics.drawable.StateListDrawable
. Todo esto se puede hacer en XML o mediante programación. Consulte la sección Botón personalizado del tutorial de Form Stuff .fuente
Creo una muestra aquí , simplemente cambie ImageView a ClickableImageView desde su diseño. Espero que te ayude.
fuente
Creo que ImageButton es una mejor solución
<ImageButton android:layout_width="96dp" android:layout_height="56dp" android:src="@mipmap/ic_launcher" android:adjustViewBounds="true" android:background="@android:color/transparent" android:foreground="@drawable/selector" />
fuente
Tengo una solución más bella si usa 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; } }); }
fuente
O:
Puede utilizar este formulario, con el botón de imagen.
Crear archivo
res/drawable/btn_video.xml
:<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/image" android:state_pressed="true" /> <item android:drawable="@drawable/ico2" android:state_focused="true" /> <item android:drawable="@drawable/ico2" /> </selector>
Y
res/layout/activity_main.xml
:<ImageButton android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/imageButton" android:layout_gravity="center_horizontal" android:onClick="eventImageBtn" android:background="@drawable/btn_video" android:adjustViewBounds="true" android:scaleType="fitXY" />
Su imagen cambia con un clic y puede ajustar con un diseño lineal:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@color/menu_item_background"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="@dimen/main_screen_side_padding" android:paddingRight="@dimen/main_screen_side_padding" android:paddingTop="@dimen/main_screen_side_padding" android:paddingBottom="@dimen/main_screen_side_padding" android:background="#ffb3ff13" android:weightSum="10.00"> <LinearLayout android:layout_weight="2.50" android:background="#ff56cfcd" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" > <ImageButton android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/imageButton" android:layout_gravity="center_horizontal" android:onClick="eventImageBtn" android:background="@drawable/btn_video" android:adjustViewBounds="true" android:scaleType="fitXY" /> </LinearLayout> <LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" > </LinearLayout> <LinearLayout android:layout_weight="4.50" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ff8aa5ff"> </LinearLayout> <LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" > </LinearLayout> <LinearLayout android:layout_weight="2.00" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ffff7d1a" > </LinearLayout> </LinearLayout> </LinearLayout> </ScrollView>
fuente
Aquí está mi solución, que, utilizando 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 rootView es la celda en sí (el diseño), y que tiene un único imageView que desea que se vea afectado por el color que desea aplicar a toda la celda.
EDITAR: si lo desea, también puede extender ImageView para manejar el primer plano y configurarlo en "? Android: attr / selectableItemBackground". Hay una biblioteca para esto aquí y un tutorial sobre cómo hacerlo para cualquier vista que desee, aquí .
fuente
Gracias por la ayuda en este hilo. Sin embargo, te perdiste una cosa ... también debes manejar ACTION_CANCEL. Si no lo hace, es posible que no restaure correctamente el valor alfa de ImageView en caso de que una vista principal en la jerarquía de vistas intercepte un evento táctil (piense en un ScrollView que envuelve su ImageView).
Aquí hay una clase completa que se basa en la clase anterior, pero también se ocupa de ACTION_CANCEL. Utiliza una clase auxiliar ImageViewCompat para abstraer las diferencias en la API de JellyBean pre-post.
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(); } }
fuente
Aquí está mi código. La idea es que ImageView obtiene un filtro de color cuando el usuario lo toca y el filtro de color se elimina cuando el usuario deja de tocarlo.
Martin Booka Weser, András, Ah Lam, altosh, la solución no funciona cuando ImageView también tiene onClickEvent. La solución worawee.s y kcoppock (con ImageButton) requiere un fondo, lo que no tiene sentido cuando ImageView no es transparente.
Esta es una extensión de la idea 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));
fuente
Lo intenté con:
<ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/get_started" android:src="@drawable/home_started" style="?android:borderlessButtonStyle" android:adjustViewBounds="true" android:clickable="true" android:elevation="5dp" android:longClickable="true" />
y esto funcionó. Tenga en cuenta en la línea:
style="?android:borderlessButtonStyle"
fuente
Creo que la forma más sencilla es crear un nuevo archivo XML. En este caso, llamémoslo "ejemplo.xml" en la carpeta dibujable y coloquemos el siguiente código:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/blue" android:state_pressed="true" /> </selector>
Pero antes de eso, debe configurar los colores en el archivo colors.xml, en la carpeta de valores, así:
<resources> <color name="blue">#0000FF</color> </resources>
Hecho eso, simplemente configura el Botón / ImageButton para usar el nuevo diseño, así:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/example" />
Luego, cuando haga clic en esa imagen, cambiará al color establecido en
<item android:drawable="@color/blue" android:state_pressed="true" />
dando la retroalimentación que desea ...
fuente
Esta es la mejor solución que he visto. Es más genérico.
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" > <alpha android:duration="100" android:fromAlpha="0.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="1.0" /> </set>
fuente
Hice lo siguiente en XML, con 0 relleno alrededor de la imagen y ondulación en la parte superior de la imagen:
<ImageView android:layout_width="100dp" android:layout_height="100dp" android:background="@drawable/my_image" android:clickable="true" android:focusable="true" android:src="?android:attr/selectableItemBackground" />
fuente
Por ahora, deberíamos desarrollar la práctica del Diseño de Materiales . En este caso, podría agregar un efecto dominó en un ImageView.
fuente
Simplemente agregue el atributo XML, android: clickable = "true" ...
fuente