web-dev-qa-db-fra.com

Android imageview change teinte pour simuler le clic du bouton

J'ai une imageview sur laquelle j'ai mis une image bitmap extraite d'une URL. Sur l'image, j'ai défini un onClickListener qui ouvre une boîte de dialogue.

Je veux en quelque sorte changer la teinte (la rendre plus sombre) lorsque l'image est pressée pour fournir une sorte de clic de bouton comme une sensation.

Que suggérez-vous?

39
Abhishek

la réponse de happydude est la façon la plus élégante de gérer cela, mais malheureusement (comme souligné dans les commentaires) le code source d'ImageView n'accepte qu'un entier (couleur unie). Issue 1822 existe depuis quelques années, j'ai publié une solution de contournement que je résumerai ici:

Étendez ImageView et encapsulez drawableStateChanged () avec du code qui définit la teinte en fonction du nouvel état:

TintableImageView.Java

package com.example.widgets;

import Android.content.Context;
import Android.content.res.ColorStateList;
import Android.content.res.TypedArray;
import Android.util.AttributeSet;
import Android.support.v7.widget.AppCompatImageView;

import com.example.R;

public class TintableImageView extends AppCompatImageView {

    private ColorStateList tint;

    public TintableImageView(Context context) {
        super(context);
    }

    public TintableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public TintableImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0);
        tint = a.getColorStateList(R.styleable.TintableImageView_tintColorStateList);
        a.recycle();
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (tint != null && tint.isStateful())
            updateTintColor();
    }    

    private void updateTintColor() {
        int color = tint.getColorForState(getDrawableState(), 0);
        setColorFilter(color);
    }

}

Définissez un attribut personnalisé:

attrs.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>

    <declare-styleable name="TintableImageView">
        <attr name="tintColorStateList" format="reference|color" />
    </declare-styleable>

</resources>

Utilisez le widget et l'attribut personnalisé avec votre espace de noms local au lieu d'Android:

example_layout.xml

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="horizontal">

    <com.example.widgets.TintableImageView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:src="@drawable/example"
        Android:clickable="true"
        app:tintColorStateList="@color/color_selector"/>

</LinearLayout>

Vous pouvez ensuite utiliser un sélecteur de couleurs comme suggéré par happydude:

color_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:state_pressed="true" Android:color="@color/pressed_color"/>
    <item Android:color="#00000000"/>
</selector>
99
Stephen Kidson

Une façon serait d'utiliser une combinaison d'un ColorFilter et d'un ColorStateList qui contient votre couleur de teinte lorsque vous appuyez sur le bouton. Le xml du ColorStateList dans le répertoire res/color ressemblerait à ceci:

button_pressed.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item Android:state_pressed="true" Android:color="@color/pressed_color"/>
    <item Android:color="#00000000"/>

</selector>

@color/pressed_color est votre couleur de teinte (qui doit être partiellement transparente). Ensuite, dans votre sous-classe ImageView, vous appliquez la couleur en remplaçant drawableStateChanged().

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();

    ColorStateList list = getResources().getColorStateList(R.color.button_pressed);
    int color = list.getColorForState(getDrawableState(), Color.TRANSPARENT);
    setColorFilter(color);
    invalidate();
}

Chaque fois que l'état du bouton change, ce code est appelé et définira automatiquement la teinte comme il convient.

7
happydude

Pour moi, une solution simple fonctionne, en utilisant setAlpha (180) in onClick l'événement rend l'image plus sombre, donnant à l'utilisateur un retour d'information indiquant qu'elle a été cliquée ou touchée.

final ImageView myImage = (ImageView) findViewById(R.id.ivDocument);
myImage.setImage...(... your image ...); // load your ImageView
myImage.setClickable(true);
myImage.setFocusable(true);
myImage.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        myImage.setAlpha(180);
        doWhateverYouWantHere(v);
    }
});

Concernant votre mise en page XML, rien de spécial.

0
Jagoliveira

Je devrais le tester, mais vous devriez pouvoir définir un xml avec ce comportement en tant que dessin ImageView, puis définir votre bitmap comme arrière-plan ImageView.

0
Charlie-Blake