Jak mogę uzyskać efekt kliknięcia widoku obrazu, taki jak przycisk w systemie Android?


84

Mam imageview w mojej aplikacji na Androida, którego używam jak przycisku z podanym zdarzeniem onClick, ale jak możesz się domyślić, po kliknięciu nie daje on efektu klikalności Imageview. Jak mogę to osiągnąć?

Odpowiedzi:


53

Możesz zaprojektować różne obrazy dla stanów klikniętych / nie klikniętych i ustawić je w onTouchListener w następujący sposób

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

Lepszym wyborem jest zdefiniowanie selektora w następujący sposób

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

i wybierz zdjęcie w przypadku:

v.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
                return true;
            }
        });

1
czy możesz wyjaśnić, co res.getDrawable res, co robi?
VenushkaT

v.setSelected tylko raz == true, natychmiast zmieniając się na false z powodu MotionEvent.ACTION_MOVE. Po zwolnieniu palca następuje MotionEvent.ACTION_UP. Jeśli używasz metody selektora, użyj oddzielnej logiki do setSelected lub setPressed. if (arg1.getAction () == MotionEvent.ACTION_DOWN) {v.setPressed (true); } else if (arg1.getAction () == MotionEvent.ACTION_UP) {v.setPressed (false); }
Adam Denoon

Lepiej, MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVEaby obraz był widoczny, dopóki naciskamy.
Alaa M.

Nie musisz setOnTouchListener(.... Możesz po prostu utworzyć, <selector ...>a następnie ustawić klikalny ImageView w XML, na przykład<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
Pierre

76

Możesz to zrobić z pojedynczym obrazem, używając czegoś takiego:

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

Prawdopodobnie zrobię to w podklasie ImageView (lub ImageButton, ponieważ jest to również podklasa ImageView), aby ułatwić ponowne użycie, ale powinno to umożliwić zastosowanie „wybranego” wyglądu do widoku obrazu.


2
Dodałem też skrzynkę dla ACTION_CANCEL, działa świetnie, dzięki!
Alan

Dobre połączenie - dodałem to we własnym kodzie, ale tutaj też zaktualizuję.
Pan Zorn

1
To może być inne pytanie, ale jak anulować po ACTION_UP? W szczególności ... Użytkownik trafia w obrazek. Użytkownik odciąga palcem obraz, aby anulować. Ale akcja nie jest anulowana za pomocą tego kodu
sudocoder

Dodam też MotionEvent.ACTION_OUTSIDE;)
bonnyz

3
możesz chcieć wrócić false, w przeciwnym razie rzeczywiste onClick()zdarzenie widoku nie zostanie uruchomione
Nimrod Dayan

45

Można to zrobić z jednym plikiem obrazu przy użyciu metody ColorFilter. Jednak ColorFilter oczekuje, że będzie działać z ImageViews, a nie Buttons, więc musisz przekształcić swoje przyciski w ImageViews. Nie stanowi to problemu, jeśli i tak używasz obrazów jako przycisków, ale jest bardziej irytujące, jeśli masz tekst ... W każdym razie, zakładając, że znajdziesz sposób na obejście problemu z tekstem, oto kod do użycia:

ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);

Powoduje to nałożenie czerwonej nakładki na przycisk (kod koloru to kod szesnastkowy całkowicie nieprzezroczystej czerwieni - pierwsze dwie cyfry to przezroczystość, a następnie jest to RR GG BB.).


3
Czy mógłbyś wyjaśnić, co się stanie po uruchomieniu tego kodu i gdzie ma on zostać wywołany? Próbowałem wywołać te dwie linie podczas inicjalizacji imageView - maluje mój obraz na czerwono i nic się wtedy nie dzieje, ani po kliknięciu, ani po dotknięciu. To samo, gdy dzwonisz na dotyk.
szacunek

45

EDYCJA : Chociaż oryginalna odpowiedź poniżej działa i jest łatwa do skonfigurowania, zapoznaj się z tym postem napisanym przez rzecznika programistów Androida w Google, jeśli chcesz / potrzebujesz bardziej wydajnej implementacji. Należy również zauważyć, że android:foregroundatrybut jest domyślnie dostępny we wszystkich widokach, w tym ImageView, w systemie Android M.


Problem z używaniem selektora dla ImageView polega na tym, że możesz ustawić go tylko jako tło widoku - dopóki obraz jest nieprzezroczysty, nie zobaczysz efektu selektora za nim.

Sztuczka polega na owinięciu ImageView w FrameLayout atrybutem, android:foregroundktóry pozwala nam zdefiniować nakładkę dla jego zawartości. Jeśli ustawimy android:foregroundselektor (np. ?android:attr/selectableItemBackgroundDla poziomu API 11+) i OnClickListenerdołączymy do FrameLayout zamiast ImageView, obraz zostanie nałożony na nasz selektor do rysowania - pożądany efekt kliknięcia!

Ujrzeć:

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

(Pamiętaj, że powinno to być umieszczone w układzie nadrzędnym).

final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View view) {
        // do whatever we wish!
    }
});

2
Świetny ! To bardzo dobre rozwiązanie. To samo rozwiązanie używane w aplikacji kontaktów dla akcji SMS lub Call.
Jerry

Będzie działać API <11. ANDROID atr / selectableItemBackground wymaga poziomu API 11 (prąd MIN 8)?
MSaudi

selectableItemBackgroundAtrybut został dodany tylko w poziomie API 11, więc trzeba użyć innego wyboru, jeśli chcesz korzystać z tego rozwiązania dla starszych poziomów API. Na przykład w przypadku jednej z moich aplikacji obsługujących poziom interfejsu API 7 używam @drawable/list_selector_holo_lightzasobu wygenerowanego za pomocą narzędzia Android Holo Colours Generator .
justasm

Możesz osiągnąć to samo zachowanie, używając tylko 1 <ImageButton>z selectableItemBackground!
Yohan Dahmani

28

Użyj style = "? Android: borderlessButtonStyle" w pliku XML. Pokaże domyślny efekt kliknięcia Androida.

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher" 
    style="?android:borderlessButtonStyle"
/>

1
To jest właściwie najlepsza odpowiedź, DUŻO łatwiejsza
FrankMonza

1
To ustawia dopełnienie, a nawet jeśli ustawisz dopełnienie na 0, jeśli podany obraz zajmie cały imageView, nie zobaczysz żadnego efektu kliknięcia.
programista Androida

2
@androiddeveloper użyj android:adjustViewBounds="true"do anulowania dopełnienia.
Hafez Divandari

1
Zaleca się użycie style="?android:attr/borderlessButtonStyle": developer.android.com/guide/topics/ui/controls/…
Hafez Divandari

21

Po prostu użyj ImageButton .


3
Osobiście nie mogę sprawić, by wyglądało jak ImageView. Bez obramowania, rozciągnij obraz do rozmiaru ImageButton itp. Jeśli możesz podać tę obramowanie i problem z rozciąganiem i zaktualizuj swój post. Moja reputacja trafia do ciebie jako bounty =)
totten

15

Oto mój prosty sposób na rozwiązanie tego problemu:

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

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

Świetne rozwiązanie - dzięki! Przewinąłem ten post, próbując wszystkich zwięzłych - bez powodzenia. W końcu tu dotarłem i to zadziałało. Jedna uwaga - jeśli masz 2+ przyciski, do których chcesz zastosować animację… dla mojego kodu, stwierdziłem, że muszę utworzyć unikalną instancję obiektu Animation dla każdego przycisku, do którego chciałem zastosować efekt. Ponowne użycie tego samego wystąpienia spowodowało migotanie wszystkich przycisków po kliknięciu 1.
Gene Bo

9

Ustaw wybieralne tło na ImageView i dodaj trochę wypełnienia. Następnie dołącz 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"/>

Czy istnieje sposób na użycie go bez ustawiania dopełnienia i sprawienie, aby cały ImageView miał efekt, a nie tylko pusty obszar?
programista Androida

To pokaże tętnienie sześcienne, potrzebujemy tętnienia środkowego
Kishan Solanki

8

Do definiowania wyboru do rysowania selektora

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

Muszę używać android: state_pressed zamiast 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>

5

Możesz spróbować z, android:background="@android:drawable/list_selector_background" aby uzyskać ten sam efekt, co „Dodaj alarm” w domyślnym „Budzik” (teraz Zegar na biurko).


5

Jeśli chcesz mieć ripple po dotknięciu, możesz podać ten kod:

<ImageView
    ...
    android:background="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    ...
</ImageView>

Podobnie możesz zaimplementować efekt kliknięcia dla TextView

<TextView
    ...
    android:background="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    ...
</TextView>

4

To zadziałało dla mnie:

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

        });

@Edit: Jak powiedział Gunhan, wystąpi problem z kompatybilnością wsteczną z metodą setImageAlpha. Użyłem tej metody:

public static void setImageAlpha(ImageView img, int alpha)
    {
        if(Build.VERSION.SDK_INT > 15)
        {
            img.setImageAlpha(alpha);
        }
        else
        {
            img.setAlpha(alpha);
        }
    }

1
setImageAlpha wymaga interfejsu API na poziomie 16. Dlatego w przypadku aplikacji kompatybilnych wstecz nie można go używać
Gunhan

1
@Gunhan właściwie możesz użyć biblioteki „nineOldAndroids”, która pozwala na używanie alfy nawet na starszych interfejsach API. po prostu użyj: ViewHelper.setAlpha (view, alpha);
programista androidów

4

Robię kilka podobnych rzeczy. Zobacz, które są dla Ciebie odpowiednie, czy nie

Zobacz pomocnika efektu prasowego:

  • użycie: wykonaj prosty efekt prasowy, taki jak iOS

    Proste użycie:

  • ImageView img = (ImageView) findViewById (R.id.img);

  • ViewPressEffectHelper.attach (img)

https://gist.github.com/extralam/7489370


4

W połączeniu ze wszystkimi powyższymi odpowiedziami chciałem, aby ImageView został naciśnięty i zmienił stan, ale jeśli użytkownik się poruszył, „anuluj” i nie wykonuj onClickListener.

Skończyło się na utworzeniu obiektu Point w klasie i ustawieniu jego współrzędnych w zależności od tego, kiedy użytkownik nacisnął ImageView. W MotionEvent.ACTION_UP nagrywam nowy punkt i porównałem punkty.

Mogę to tylko dobrze wyjaśnić, ale oto co zrobiłem.

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

Mam ustawiony onClickListener na imageView, ale może to być metoda.


dodając skrzynkę MotionEvent.ACTION_CANCELz taką samą funkcjonalnością jak MotionEvent.ACTION_UPwtedy możliwe jest „wyczyszczenie” widoku, jeśli użytkownik wykona „przeciągnięcie”, które nie jest akcją kliknięcia.
Mando Stam

4

Możesz Override setPressedw ImageView i tam wykonać filtrowanie kolorów, zamiast tworzyć detektory 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();
    }
}

4

W oparciu o odpowiedź pana Zorna używam metody statycznej w mojej abstrakcyjnej klasie Utility:

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

    ...
}

Następnie używam go z 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)

Jest to bardzo proste, jeśli masz dużo obrazów i chcesz mieć prosty efekt onTouch, bez żadnego XML-a do rysowania i tylko jeden obraz.




3

Myślę, że ImageButton jest lepszym rozwiązaniem

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

2

Mam bardziej upiększające rozwiązanie, jeśli używasz obrazów tła :)

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

2

LUB:

Możesz użyć tego formularza, z przyciskiem Obraz.

Utwórz plik 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>

Oraz 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"
/>

Twój obraz zmienia się jednym kliknięciem i możesz dostosować go za pomocą układu liniowego:

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

2

Oto moje rozwiązanie, które przy użyciu biblioteki „ nineOldAndroids ” obsługuje również stare interfejsy API:

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

Zakłada się, że rootView jest samą komórką (układem) i ma pojedynczy imageView, na który chcesz wpływać kolor, który chcesz zastosować do całej komórki.


EDYCJA: jeśli chcesz, możesz również rozszerzyć ImageView, aby obsługiwał pierwszy plan i ustawić go na „? Android: attr / selectableItemBackground”. Jest to biblioteka do tego tutaj i tutorial jak to zrobić dla dowolnego widoku chcesz, tutaj .


@madlymad dziękuję za naprawienie formatowania kodu, chociaż myślę, że coś poszło nie tak z wcięciami. Tak czy inaczej, wystarczy to przeczytać ...
programista android

1

Dzięki za pomoc w tym wątku. Jednak przegapiłeś jedną rzecz ... musisz też obsłużyć ACTION_CANCEL. Jeśli tego nie zrobisz, możesz nieprawidłowo przywrócić wartość alfa ImageView w przypadku, gdy widok nadrzędny w hierarchii widoków przechwytuje zdarzenie dotykowe (pomyśl, że ScrollView otacza cię ImageView).

Oto pełna klasa, która jest oparta na powyższej klasie, ale zajmuje się również ACTION_CANCEL. Używa klasy pomocniczej ImageViewCompat, aby wyodrębnić różnice w interfejsie API JellyBean przed opublikowaniem.

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

1

Oto mój kod. Chodzi o to, że ImageView pobiera filtr kolorów, gdy użytkownik go dotknie, a filtr kolorów jest usuwany, gdy użytkownik przestaje go dotykać.

Martin Booka Weser, András, Ah Lam, altosh, rozwiązanie nie działa, gdy ImageView ma również onClickEvent. worawee.s i kcoppock (z ImageButton) wymaga tła, co nie ma sensu, gdy ImageView nie jest przezroczysty.

Ten jest rozwinięciem pomysłu AZ_ na temat filtra koloru.

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

stosowanie:

Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));

1

Próbowałem z:

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

i to zadziałało. Uwaga na linii:style="?android:borderlessButtonStyle"


To nie działa w przypadku wypełnienia 0, a obraz zajmuje cały obszar widoku.
programista Androida

1

Myślę, że najłatwiejszym sposobem jest utworzenie nowego pliku XML. W tym przypadku nazwijmy to „example.xml” w folderze do rysowania i wstawmy następujący kod:

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

</selector>

Ale wcześniej musisz ustawić kolory w pliku colors.xml, w folderze wartości, na przykład:

<resources>
    <color name="blue">#0000FF</color>
</resources>

To sprawiło, że po prostu ustawiłeś Button / ImageButton, aby używał nowego układu, na przykład:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/example"
/>

Następnie po kliknięciu tego obrazu zmieni się on na ustawiony kolor

<item android:drawable="@color/blue"
      android:state_pressed="true" />

przekazując informacje zwrotne, które chcesz ...


1

To najlepsze rozwiązanie, jakie kiedykolwiek widziałem. Jest bardziej ogólny.

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

2
W jakim miejscu i pliku należy go wstrzyknąć?
DmitryBoyko

0

Zrobiłem co następuje w XML - z dopełnieniem 0 wokół obrazu i falowaniem na górze obrazu:

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


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.