Jak ustawić efekt kliknięcia przycisku w systemie Android?


105

W Androidzie, kiedy ustawię obraz tła na przycisk, nie widzę żadnego efektu na przycisku.

Potrzebuję jakiegoś efektu na przycisku, aby użytkownik mógł rozpoznać, że przycisk został kliknięty.

Przycisk powinien być ciemny przez kilka sekund po kliknięciu, więc co mam z tym zrobić?

Dzięki.



Poniższa metoda umożliwia użycie jednej klasy stylów do skórowania wszystkich przycisków, niezależnie od ich tekstu: stackoverflow.com/questions/5327553/…
Zack Marrapese

nie, nie używam przycisku obrazu, używam przycisku normalnego w prosty sposób?
Jignesh Ansodariya

Odpowiedzi:


154

Można to osiągnąć, tworząc nadający się do rysowania plik xml zawierający listę stanów przycisku. Na przykład, jeśli utworzysz nowy plik xml o nazwie „button.xml” z następującym kodem:

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

Aby zachować przyciemniony obraz tła w druku, utwórz drugi plik xml i nazwij go gradient.xml z następującym kodem:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <bitmap android:src="@drawable/YOURIMAGE"/>
    </item>
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
        </shape>
    </item>
</layer-list>

W pliku XML twojego przycisku ustaw tło na przycisk xml np

android:background="@drawable/button"

Mam nadzieję że to pomoże!

Edycja: Zmieniono powyższy kod, aby wyświetlać obraz (YOURIMAGE) na przycisku, a nie kolor bloku.


To gdzie mogę ustawić obraz jako tło przycisku, aby ustawić obraz jest konieczny
Jignesh Ansodariya

1
Edytowano, aby pokazać, jak używać obrazu tła ze stanem XML. Zastąp YOURIMAGE zasobem obrazu w katalogu do rysowania.
Ljdawson

Działa to tylko wtedy, gdy src przycisku jest prostokątne. Jeśli element src drawable ma inny kształt niż ten, gradient zostanie również zastosowany do tła i jest to smutne.
Renato Lochetti

Nie bardzo, zawsze można użyć innego kształtu na liście warstw
Ljdawson

2
podczas gdy używam obrazu, to działa dla mnie .. ale kiedy używam tła XML. nie działa ...
DKV

88

Jest to prostsze, gdy masz dużo przycisków graficznych i nie chcesz pisać xml-s dla każdego przycisku.

Wersja Kotlin:

fun buttonEffect(button: View) {
    button.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
                v.invalidate()
            }
            MotionEvent.ACTION_UP -> {
                v.background.clearColorFilter()
                v.invalidate()
            }
        }
        false
    }
}

Wersja Java:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

2
Używam tego w swoim kodzie i jedyny problem, jaki zauważyłem do tej pory, to to, że przycisk zachowuje się dziwnie po umieszczeniu w ScrollView.
Finnboy11

To naprawdę świetne rozwiązanie i to powinna być poprawna odpowiedź
Biraj Zalavadia

Jak to jest lepsze? Projektowanie należy trzymać poza kodem, prawda?
Błędy wydarzyły się

To tylko proste rozwiązanie tego problemu. Jeśli masz wiele przycisków i nie chcesz tworzyć plików XML dla każdego z nich, może to być pomocne.
András

O mój Boże! Wyobraź sobie, że masz 5 przycisków we fragmencie ... Będziesz miał całą masę tego standardowego kodu ... Jak więc to zreformować? Zmienić filtr kolorów dla wszystkich przycisków we wszystkich działaniach? Imho to twój następny programista nie będzie taki szczęśliwy ..
Leo Droidcoder

84

Stwórz swój AlphaAnimationobiekt, który decyduje o tym, jaki będzie efekt zanikania przycisku, a następnie pozwól mu rozpocząć się w jednym onClickListenerz przycisków

Na przykład :

private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

public void onClick(View v) {
    v.startAnimation(buttonClick);
}

oczywiście to tylko sposób, nie najbardziej preferowany, jest po prostu łatwiejszy


5
To, co podoba mi się w tym rozwiązaniu, to to, że nie wymaga tworzenia wielu selektorów, gdy masz wiele przycisków z własnymi niestandardowymi obrazami.
Pete,

2
Nie powoduje to zaniku przycisku przy dotknięciu, a jedynie wygaszenie go na ułamek sekundy po wykryciu kliknięcia i podniesieniu palca użytkownika.
Doug Voss

1
Ładnie i prosto

@Doug Voss, możesz ustawić czas trwania animacji, aby ją wydłużyć
Ahmed Adel Ismail

a co z onLongClick i „roundReveal”?
Acauã Pitta

45

Można po prostu wykorzystać nową wiedzę dla Twojego Viewosiągnąć efekt klikalny:

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


Do użytku z ciemnym motywem dodaj także motyw do swojego layout(aby klikalny efekt był jasny):

android:theme="@android:style/ThemeOverlay.Material.Dark"

5
Najłatwiejszy sposób wdrożenia. Do Twojej wiadomości, Atrybut android: foreground nie ma wpływu na poziomy API niższe niż 23.
dolgom

1
Najprostsze rozwiązanie.
Jerry Chong

2
To powinna być akceptowana odpowiedź, znacznie prostsza i dodaje przyjemny efekt animacji tętnienia.
Tyler

1
@dolgom Dla poziomu API <23 użyj go w atrybucie "background". Więc: android: background = "? android: attr /
selectableItemBackground

24

Aby element był spójny z wyglądem i działaniem systemu, spróbuj odnieść się do atrybutu systemowego android:attr/selectableItemBackgroundw tagu tła lub pierwszego planu żądanego widoku:

<ImageView
    ...
    android:background="?android:attr/selectableItemBackground"      
    android:foreground="?android:attr/selectableItemBackground"
    ...
/>

Użyj obu atrybutów, aby uzyskać pożądany efekt odpowiednio przed / po 23 poziomie API.

https://stackoverflow.com/a/11513474/4683601


2
Zdecydowanie najprostsze rozwiązanie. Dzięki!
tykom

9

Lub używając tylko jednego obrazu tła, możesz osiągnąć efekt kliknięcia używając setOnTouchListener

Dwie drogi

((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {

      @Override
        public boolean onTouch(View v, MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN: {
                  Button view = (Button) v;
                  view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
                  v.invalidate();
                  break;
              }
              case MotionEvent.ACTION_UP:
                  // Your action here on button click
              case MotionEvent.ACTION_CANCEL: {
                  Button view = (Button) v;
                  view.getBackground().clearColorFilter();
                  view.invalidate();
                  break;
              }
          }
          return true;
        }
});

wprowadź opis obrazu tutaj

A jeśli nie chcesz używać setOnTouchLister, innym sposobem na osiągnięcie tego jest

    myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);

    myButton.setBackgroundDrawable(listDrawable);

są błędy w kodzie w 2. sposób. Co to jest funkcja getCurrent ()? Również myButton nie jest Drawable, więc nie można go dodać jako stanu.
Ehtesham Hasan,

Dziękuję za wskazanie błędu. Poprawiłem to, a myButton jest instancją klasy Button, która dostarcza metodę setBackgroundDrawable i pobiera instancje Drawable, więc to zadziała.
Vinayak Bevinakatti

Sprawdź moją odpowiedź, która jest oparta na Twoim drugim podejściu. stackoverflow.com/a/39430738/5229515
Ehtesham Hasan

Powinno to prawdopodobnie mieć na końcu „return false”, aby nie zużywało zdarzenia i można było wywołać jakiekolwiek dodatkowe onClickListeners.
Doug Voss

3

po prostu chcę dodać inny łatwy sposób, aby to zrobić: Jeśli twój ImageButton pozostaje tłem i nie ustawisz go na null, będzie działał jak normalny przycisk i wyświetli animację kliknięcia podczas klikania dokładnie tak, jak inne przyciski. tło, gdy jeszcze tam jest:

<ImageButton
    android:id="@+id/imageButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="1dp"
    android:paddingLeft="1dp"
    android:paddingRight="1dp"
    android:paddingTop="1dp"
    android:src="@drawable/squareicon" />

Wypełnienia nie pozwolą, aby tło było widoczne i sprawi, że przycisk będzie działał jak inne przyciski.


1
to zachowa kwadratową ramkę przycisku wokół obrazu, jeśli jest okrągła
MSaudi

3

To najlepsze rozwiązanie, jakie wymyśliłem, biorąc wskazówki z odpowiedzi @ Vinayak. Wszystkie inne rozwiązania mają różne wady.

Przede wszystkim utwórz taką funkcję.

void addClickEffect(View view)
{
    Drawable drawableNormal = view.getBackground();

    Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
    drawablePressed.mutate();
    drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {}, drawableNormal);
    view.setBackground(listDrawable);
}

Wyjaśnienie:

getConstantState (). newDrawable () służy do klonowania istniejącego Drawable, w przeciwnym razie zostanie użyty ten sam drawable. Przeczytaj więcej tutaj: Android: klonowanie elementu do rysowania w celu utworzenia StateListDrawable z filtrami

mutate () służy do tego, aby klon Drawable nie współdzielił swojego stanu z innymi wystąpieniami Drawable. Przeczytaj więcej na ten temat tutaj: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Stosowanie:

Możesz przekazać dowolny typ widoku (Button, ImageButton, View itp.) Jako parametr do funkcji, a uzyskają zastosowany do nich efekt kliknięcia.

addClickEffect(myButton);
addClickEffect(myImageButton);

2
Step: set a button in XML with onClick Action:

 <Button
android:id="@+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/txt_height"
android:layout_gravity="center"
android:background="@drawable/round_btn"
android:contentDescription="@string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="@dimen/login_textSize" />

Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- -----  ---- ---- -----

    public void edit_user_info(View view) {

        // show click effect on button pressed
        final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
        view.startAnimation(buttonClick);

        Intent intent = new Intent(getApplicationContext(),  EditUserInfo.class);
        startActivity(intent);

    }// end edit_user_info

2

Użyj RippleDrawable dla efektu wciśnięcia / kliknięcia stanu Material Design.

Aby to osiągnąć, utwórz element ripple jako folder .xml under / drawable i użyj go w android: background dla dowolnych widoków.

  • Efekt po naciśnięciu / kliknięciu ikony, użyj efektu tętnienia kołowego, na przykład:

    <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@android:color/darker_gray" />

  • Efekt dla widoku klikniętego granicą prostokąta, możemy dodać tętnienie na istniejącym rysunku, jak poniżej:

    <?xml version="1.0" encoding="utf-8"?> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#000000"> <item android:drawable="@drawable/your_background_drawable"/> </ripple>


2

Za wszystkie widoki

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

Ale dla widoku karty, który ma zastosowanie elewacji

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

Efekt kliknięcia kołowego jak na pasku narzędzi

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

Musisz także ustawić

 android:clickable="true"
 android:focusable="true"

0

Drobny dodatek do odpowiedzi Andràs:

Możesz użyć, postDelayedaby filtr koloru trwał przez krótki czas, aby był bardziej zauważalny:

        @Override
        public boolean onTouch(final View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            v.getBackground().clearColorFilter();
                            v.invalidate();
                        }
                    }, 100L);
                    break;
                }
            }
            return false;
        }

Możesz zmienić wartość opóźnienia 100L zgodnie ze swoimi potrzebami.


0

Jeśli używasz tła XML zamiast IMG, po prostu usuń to:

<item>
    <bitmap android:src="@drawable/YOURIMAGE"/>
</item>

z pierwszej odpowiedzi, którą dał nam @Ljdawson.


0

Utwórz plik bounce.xml do animacji

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

    <scale
        android:duration="100"
        android:fromXScale="0.9"
        android:fromYScale="0.9"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>

Dodaj tę linię w onClick, aby zainicjować

final Animation myAnim = AnimationUtils.loadAnimation (this, R.anim.bounce); button.startAnimation (myAnim);

Efekt zmniejszania się uzyskuje się po kliknięciu przycisku.

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.