2010-11-15 15 views
40

Un buen ejemplo de esto es en la pantalla de inicio de Twitter (la pantalla con los íconos grandes que se ven cuando se lanza la aplicación por primera vez) o simplemente mire la bandeja de la aplicación cuando enfoca un icono de la aplicación.¿Cómo resaltar ImageView cuando se enfoca o se hace clic?

Básicamente necesito resaltar un ImageView donde los contornos resaltan 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 sea de cierto color y se desvanezca.

Gracias,

groomsy

Respuesta

78

Es necesario asignar el atributo src del ImageView una lista dibujable estado. En otras palabras, esa lista de estado tendría una imagen diferente para seleccionado, presionado, no seleccionado, etc. - así es como lo hace la aplicación Twitter.

Así que si había un ImageView:

<ImageView style="@style/TitleBarLogo" 
      android:contentDescription="@string/description_logo" 
      android:src="@drawable/title_logo" /> 

El dibujable src (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> 

El Google IO Schedule app tiene un buen ejemplo de esto.

+0

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 la aplicación, los íconos de la aplicación hacen esto. Gracias por tu ayuda. – groomsy

+2

Bueno, es posible establecer el src en su imagen y luego establecer el atributo de fondo en una lista de selectores. 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 intentado. –

+1

En realidad, ahora que lo pienso, el cajón de la aplicación utiliza un diseño de cuadrícula.Por lo tanto, cuando tiene una imagen en una cuadrícula, al seleccionarla se resaltará la celda de la cuadrícula. El proyecto de ejemplo de demostraciones de API que viene con el SDK tiene un código de ejemplo para una vista de cuadrícula. –

2

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); 
+1

Creo que [esto] (http://stackoverflow.com/a/10724364/1099884) también podría darnos pistas. He agregado 'OnFocusChangeListener' en' ImageVIew'. Con 'hasFocus', diga' imageVIew.setColorFilter (theColor); ' – Yeung

+0

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

+0

Sí, tienes razón. Y también podemos clonar el dibujable resultante fácilmente con 'drawable.getConstantState(). NewDrawable()'. Puede evitar que las imageViews que usan el mismo dibujo actualicen su estado juntas cuando solo quiero un cambio de estado dibujable de ImageView. – Yeung

1

junté pequeña biblioteca que debe ayudar con eso: https://github.com/noveogroup/Highlightify

Básicamente se crea en el selector de tiempo de ejecución, y debe ser muy fácil de usar. Aunque, el estado enfocado aún no es compatible ...

2

Solo para completar la respuesta de Josh Clemm. También puede mantener la misma imagen definida por src, pero cambie o resalte 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 definir el fondo de su botón como logo_box:

<ImageView 
    android:contentDescription="@string/description_logo" 
    android:src="@drawable/logo" 
    android:background="@drawable/logo_box" /> 

Dónde background_normal y background_pressed puede ser tan complejo como usted quiere, o tan simple como un @color :)

+0

también tenemos que agregar 'android: clickable =" true "' – Choletski

2

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

Paso 1: declarar-styleable

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


Paso 2: ImageView encargo

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: establecer 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="@drawable/icon_home"/> 


25

Si usted no tiene otra estirable para el estado presionado puede utilizar setColorFilter para lograr un simple efecto de tinte.

Se comporta como el selector de estado pulsado, 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 dedo en movimiento fuera de los límites de la vista, por lo tanto, si ocurre, restaura un fondo predeterminado.

Es importante devolver false del método onTouch cuando también desee admitir onClickListner.

+0

hombre, esto es lo que necesito, pero en mi caso solo resalta la última imagen en un HorizontaScrollView. ¿Sabes qué podría causar esto? thnks – FpontoDesenv

+0

Sí, es importante devolver el valor falso para permitir que se activen los eventos de clic, pero si devuelve falso, nunca se invocará su acción arriba y movimiento. ¿Qué hacer en esta situación? –

+0

@Sebastien eliminar onClickListener y mover la lógica de él a onTouchListener. Siempre puede implementar el clic como un evento táctil. – mklimek

2

Esta es una extensión de mklimek. No pude hacer que funcione correctamente desde su fragmento. He editado un poco

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

View.OnTouchListener listener = new View.OnTouchListener() { 
     private Rect rect; 
     @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; 
     } 
    }; 
1

me di cuenta de que un xml estirable no es suficiente:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/ic_filter_up" android:state_pressed="true"/> 
    <item android:drawable="@drawable/ic_filter_up_shadow"/> 
</selector> 

Un ImageView no puede pulsarse. También debe asignar un OnClickListener para un ImageView. Luego presionará como un botón.

Cuestiones relacionadas