web-dev-qa-db-fra.com

Comment mettre en surbrillance ImageView lorsqu'il est focalisé ou cliqué?

Un bon exemple de cela est soit sur l'écran de lancement de Twitter (l'écran avec les grandes icônes qui est visible lorsque l'application est lancée pour la première fois) ou même simplement regarder le plateau d'application lorsque vous concentrez une icône d'application.

Fondamentalement, j'ai besoin de mettre en surbrillance une ImageView où la surbrillance contourne l'image dans ImageView et ressemble à une bordure de cette image. Je voudrais également personnaliser le surlignage pour qu'il soit d'une certaine couleur et pour qu'il disparaisse.

Merci,

groomy

44
groomsy

Vous devez affecter l'attribut src de ImageView une liste d'états à dessiner. En d'autres termes, cette liste d'état aurait une image différente pour sélectionnée, pressée, non sélectionnée, etc. - c'est ainsi que l'application Twitter le fait.

Donc, si vous aviez une ImageView:

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

Le src drawable (title_logo.xml) ressemblerait à ceci:

<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>

Google IO Schedule app en a un bon exemple.

81
Josh Clemm

Si vous n'avez pas d'autre dessinable pour l'état pressé, vous pouvez utiliser setColorFilter pour obtenir un effet de teinte simple.

Il se comporte exactement comme le sélecteur d'état enfoncé, de sorte que lorsque vous appuyez sur l'image, l'arrière-plan devient gris clair.

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;
        }
    });

Il gère le déplacement du doigt en dehors des limites de la vue, donc s'il se produit, il restaure un arrière-plan par défaut.

Il est important de renvoyer false à partir de la méthode onTouch lorsque vous souhaitez également prendre en charge onClickListner.

26
klimat

Il s'agit d'une extension de mklimek. Je ne pouvais pas le faire fonctionner correctement à partir de son extrait. J'ai un peu édité

 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;
        }
    };
2
SilleBille

Pour afficher des images dynamiques, vous pouvez utiliser un LayerDrawable pour la source d'image.

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

Seulement pour terminer la réponse de Josh Clemm. Vous pouvez également conserver la même image définie par src, mais modifier ou mettre en surbrillance uniquement l'arrière-plan. Cela ressemblerait plus ou moins à ceci:

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>

Et puis définir l'arrière-plan de votre bouton comme logo_box:

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

Où background_normal et background_pressed peuvent être aussi complexes que vous le souhaitez, ou aussi simples qu'un @color :)

2
jsidera

Ma solution, attribut personnalisé pour ImageView:
https://github.com/henrychuangtw/Android-ImageView-hover

Étape 1: déclarer-styleable

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


Étape 2: ImageView personnalisée

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;
    }
};

}


Étape 3: déclarer myattr: xmlns: myattr = "http://schemas.Android.com/apk/res-auto" dans la mise en page 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">


Étape 4: définissez myattr: hover_res pour 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"/>


2
HenryChuang

J'ai remarqué qu'un xml dessinable ne suffit pas:

<?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>

Une ImageView n'appuie pas. Vous devez également affecter un OnClickListener pour une ImageView. Ensuite, il appuiera sur un bouton.

1
CoolMind

J'ai mis en place une petite bibliothèque qui devrait aider à cela: https://github.com/noveogroup/Highlightify

Fondamentalement, il crée un sélecteur lors de l'exécution et devrait être très facile à utiliser. Cependant, l'état concentré n'est pas encore pris en charge ...

1
Roman Zhilich

J'utilise Android:state_selected="true" Pour state of imageView.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@drawable/ic_enable" Android:state_selected="true" />

    <item Android:drawable="@drawable/ic_disable" Android:state_selected="false" />

    <!--for default-->
    <item Android:drawable="@drawable/ic_enable" />

</selector>

utilisez img_view.setSelected(true) OU img_view.setSelected(false) pour changer l'état de l'image dans Java/kotlin code .

0
Geet Thakur

Utilisez selectableItemBackground comme arrière-plan:

Android:background="?android:attr/selectableItemBackground"
0
slowcar