¿Cómo resaltar ImageView cuando se enfoca o se hace clic?

8 minutos de lectura

Un buen ejemplo de esto es la pantalla de inicio de Twitter (la pantalla con los íconos grandes que se ve cuando la aplicación se inicia por primera vez) o simplemente mire la bandeja de la aplicación cuando enfoca el ícono de una aplicación.

Básicamente, necesito resaltar un ImageView donde el resaltado se contornea a la imagen dentro de ImageView y parece que es un borde de esa imagen. También me gustaría personalizar el resaltado para que tenga un color determinado y se desvanezca.

Gracias,

acicalado

Tienes que asignar el src atributo de la ImageView una lista de estados dibujable. En otras palabras, esa lista de estados tendría una imagen diferente para seleccionado, presionado, no seleccionado, etc. – así es como lo hace la aplicación de Twitter.

Entonces, si tuviera un ImageView:

<ImageView style="@style/TitleBarLogo"
            android:contentDescription="@string/description_logo"
            android:src="https://stackoverflow.com/questions/4185930/@drawable/title_logo" />

El src dibujable (title_logo.xml) se vería así:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/title_logo_pressed"/>
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/title_logo_pressed"/>
    <item android:state_focused="true" android:drawable="@drawable/title_logo_selected"/>
    <item android:state_focused="false" android:state_pressed="false" android:drawable="@drawable/title_logo_default"/>
</selector>

los Aplicación Google IO Schedule tiene un buen ejemplo de esto.

  • Sabía que podía hacer esto, pero me preguntaba si había una forma integrada de manejar esto. Como dije, sé que en el cajón de aplicaciones, los íconos de las aplicaciones hacen esto. Gracias por tu ayuda.

    – acicalado

    15 de noviembre de 2010 a las 16:40


  • Bueno, es posible establecer el src en su imagen y luego establecer el atributo de fondo en una lista de selección. Para el estado normal, puede mostrar una transparencia y, luego, para seleccionar, puede mostrar el degradado verde. Creo que debería funcionar, pero nunca lo he probado.

    –Josh Clemm

    15 de noviembre de 2010 a las 16:44

  • En realidad, ahora que lo pienso, el cajón de la aplicación usa un diseño de cuadrícula. Entonces, cuando tiene una imagen en una cuadrícula, seleccionarla hará que la celda de la cuadrícula se resalte. El proyecto de muestra de demostraciones de API que viene con el SDK tiene un código de ejemplo para una vista de cuadrícula.

    –Josh Clemm

    15 de noviembre de 2010 a las 16:48


  • No olvides agregar android:clickable=”true” en ImageView.

    – Canción

    27 de octubre de 2015 a las 0:43

avatar de usuario
clima

Si no tiene otro dibujable para el estado presionado, puede usar setColorFilterpara lograr un efecto de tinte simple.

Se comporta como un selector de estado presionado, por lo que cuando se presiona la imagen, cambia el fondo a un color gris claro.

final ImageView image = (ImageView) findViewById(R.id.my_image);
image.setOnTouchListener(new View.OnTouchListener() {
        private Rect rect;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                image.setColorFilter(Color.argb(50, 0, 0, 0));
                rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
            }
            if(event.getAction() == MotionEvent.ACTION_UP){
                image.setColorFilter(Color.argb(0, 0, 0, 0));
            }
            if(event.getAction() == MotionEvent.ACTION_MOVE){
                if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
                    image.setColorFilter(Color.argb(0, 0, 0, 0));
                } 
            }
            return false;
        }
    });

Maneja el movimiento del dedo fuera de los límites de la vista, por lo tanto, si ocurre, restaura un fondo predeterminado.

es importante volver false de onTouch método cuando quieras apoyar onClickListner también.

  • hombre, esto es lo que necesito, pero en mi caso está resaltando solo la última imagen en un HorizontaScrollView. ¿Sabes qué podría causar esto? gracias

    – FpontoDesenv

    19 de julio de 2015 a las 22:08

  • Sí, es importante devolver false para permitir que se activen los eventos de clic, pero si devuelve false, nunca se llamará a su acción up & move. ¿Qué hacer en esta situación?

    – Sébastien BATEZAT

    9 febrero 2016 a las 22:15

  • @Sebastien elimina onClickListener y mueve la lógica de este a onTouchListener. Siempre puede implementar el clic como un evento táctil.

    – clima

    10 de febrero de 2016 a las 7:09

  • Sí, seguro que es posible, pero estoy trabajando con una vista de cuadrícula y me gustaría mantener mi onItemClickListener. He intentado llamar a view.performClick en mi oyente táctil pero no tiene efecto. Lástima que no hay mejores opciones. Gracias de cualquier manera

    – Sébastien BATEZAT

    10 de febrero de 2016 a las 9:42

Use selectableItemBackground como fondo:

android:background="?android:attr/selectableItemBackground"

avatar de usuario
SilleBille

Esta es una extensión de mklimek. No pude hacer que funcionara correctamente a partir de su fragmento. edité un poco

 ImageView testImage = (ImageView)findViewById(R.id.imageView);
 testImage.setOnTouchListener(listener);

 View.OnTouchListener listener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {


            ImageView image = (ImageView) v;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    image.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
                    image.invalidate();                        
                    break;

                case MotionEvent.ACTION_UP:                        
                case MotionEvent.ACTION_CANCEL: {
                    //clear the overlay
                    image.getDrawable().clearColorFilter();
                    image.invalidate();
                    break;
                }
            }

            return true;
        }
    };

Para mostrar imágenes dinámicas, puede usar un LayerDrawable para la fuente de la imagen.

LayerDrawable d = new LayerDrawable(new Drawable[]{new BitmapDrawable(myBmp), getResources().getDrawable(R.drawable.my_selector_list)});
imageView.setImageDrawable(d);

  • Creo que esto también podría darnos una pista. he añadido OnFocusChangeListener en ImageVIew. Con hasFocusdecir imageVIew.setColorFilter(theColor);

    – Yeung

    3 de diciembre de 2013 a las 10:48

  • con mi solución, también obtendrá el resto de los estados y no tendrá que rastrearlo usted mismo, siempre que su lista de estados dibujable esté configurada para los estados que desea. Todo lo que haces es configurar la imagen dibujable y listo.

    – Tom Bolwitt

    12 de diciembre de 2013 a las 17:44

  • Sí, tiene usted razón. Y también podemos clonar el dibujable resultante fácilmente con drawable.getConstantState().newDrawable(). Puede evitar que las vistas de imagen usen la misma actualización dibujable de su estado cuando solo quiero un cambio de estado dibujable de ImageView.

    – Yeung

    18 de diciembre de 2013 a las 3:13

avatar de usuario
jsidera

Solo para completar la respuesta de Josh Clemm. También puede mantener la misma imagen definida por src, pero cambiar o resaltar solo el fondo. Esto sería más o menos así:

logo_box.xml

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

Y luego definiendo el fondo de su botón como logo_box:

<ImageView
    android:contentDescription="@string/description_logo"
    android:src="https://stackoverflow.com/questions/4185930/@drawable/logo"
    android:background="@drawable/logo_box" />

Donde background_normal y background_pressed pueden ser tan complejos como quieras, o tan simples como un @color 🙂

  • Creo que esto también podría darnos una pista. he añadido OnFocusChangeListener en ImageVIew. Con hasFocusdecir imageVIew.setColorFilter(theColor);

    – Yeung

    3 de diciembre de 2013 a las 10:48

  • con mi solución, también obtendrá el resto de los estados y no tendrá que rastrearlo usted mismo, siempre que su lista de estados dibujable esté configurada para los estados que desea. Todo lo que haces es configurar la imagen dibujable y listo.

    – Tom Bolwitt

    12 de diciembre de 2013 a las 17:44

  • Sí, tiene usted razón. Y también podemos clonar el dibujable resultante fácilmente con drawable.getConstantState().newDrawable(). Puede evitar que las vistas de imagen usen la misma actualización dibujable de su estado cuando solo quiero un cambio de estado dibujable de ImageView.

    – Yeung

    18 de diciembre de 2013 a las 3:13

avatar de usuario
HenryChuang

Mi solución, atributo personalizado para ImageView:
https://github.com/henrychuangtw/Android-ImageView-hover

Paso 1: declarar-estilo

<declare-styleable name="MyImageViewAttr">
    <attr name="hover_res" format="reference" />
</declare-styleable>

Paso 2: ImageView personalizado

public class MyImageView extends ImageView {

int resID, resID_hover;

public MyImageView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}
public MyImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub

    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
    resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
    if(resID_hover != -1){
        int[] attrsArray = new int[] {
                android.R.attr.src 
            };

        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
        resID = ta.getResourceId(0 , View.NO_ID);           
        ta.recycle();

        setOnTouchListener(listener_onTouch);
    }

    array.recycle();

}
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
    resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
    if(resID_hover != -1){
        int[] attrsArray = new int[] {
                android.R.attr.src 
            };

        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
        resID = ta.getResourceId(0 , View.NO_ID);           
        ta.recycle();

        setOnTouchListener(listener_onTouch);
    }

    array.recycle();
}



OnTouchListener listener_onTouch = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            setImageResource(resID_hover);
            break;

        case MotionEvent.ACTION_MOVE:

            break;

        case MotionEvent.ACTION_UP:
            setImageResource(resID);
            break;

        default:
            break;
        }


        return false;
    }
};

}

Paso 3: declarar myattr: xmlns:myattr=”http://schemas.android.com/apk/res-auto” en el diseño xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myattr="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

Paso 4: configura myattr:hover_res para MyImageView

<dev.henrychuang.component.MyImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        myattr:hover_res="@drawable/icon_home_h"
        android:src="https://stackoverflow.com/questions/4185930/@drawable/icon_home"/>

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad