Dodawanie efektu Ripple do elementu RecyclerView

108

Próbuję dodać efekt Ripple do elementu RecyclerView. Zajrzałem do Internetu, ale nie mogłem znaleźć tego, czego potrzebowałem. Zakładam, że ma to być efekt niestandardowy. Wypróbowałem atrybut android: background na sam RecyclerView i ustawiłem go na „? Android: selectableItemBackground”, ale to nie zadziałało .:

    <android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:clickable="true"
    android:background="?android:selectableItemBackground"
    android:id="@+id/recyclerView"
    android:layout_below="@+id/tool_bar"/>

To jest RecyclerView, do którego próbuję dodać efekt:

wprowadź opis obrazu tutaj

Georgi Koemdzhiev
źródło
1
Otwieram to ponownie, ponieważ nie jest to duplikat tego pytania . Chociaż rozwiązania mogą być podobne, istnieją pewne aspekty posiadania CardVieww tej kwestii, niż nie dotyczą tego bardziej ogólnego pytania.
Suragch
@Suragch Dziękuję za zauważenie różnicy :)
Georgi Koemdzhiev

Odpowiedzi:

225

Zorientowałem się. Jedyne, co musiałem zrobić, to dodać ten atrybut:

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

do głównego elementu układu, który mój adapter RecyclerView jest zawyżany w następujący sposób:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:background="?android:attr/selectableItemBackground"
    tools:background="@drawable/bg_gradient">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginLeft="15dp"
        android:layout_marginStart="15dp"
        android:id="@+id/shoppingListItem"
        android:hint="@string/enter_item_hint"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"/>

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/shopping_list_item_checkbox_label"
        android:id="@+id/shoppingListCheckBox"
        android:layout_centerVertical="true"
        android:layout_marginRight="15dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:checked="false"/>

</RelativeLayout>

Wynik:

wprowadź opis obrazu tutaj

Jeśli nadal nie możesz zobaczyć efektu tętnienia, dodaj te linie również do głównego elementu układu.

android:clickable="true"
android:focusable="true"
Georgi Koemdzhiev
źródło
3
Co się stanie, jeśli elementem głównym jest CardView?
Nabin
7
@SpiderMan Powinieneś napisać swój kod wewnątrz układu względnego lub liniowego, a następnie umieścić go wewnątrz układu karty.
SanVed
7
@pronoobsanved, to mi pomogło! Dla tych, którzy nadal borykają się z problemem, CardView przyjmuje pojedynczy układ jako dziecko. Dla tego dziecka ustaw klikalność, ustawianie ostrości jako prawdziwe i tło jako? Attr / selectedableItemBackground
Vamsi Challa
42
@NabinKhadka dla CardView zamiast tego ustaw go jako pierwszy plan, tj.android:foreground="?android:attr/selectableItemBackground"
Lorne Laliberte
6
Musiałem dodać opcję android:clickable="true"również, aby ta działała
Joaquin Iurchuk
71

Jak już odpowiedzieliśmy, najprostszym rozwiązaniem jest dodanie jednego z poniższych elementów jako RecyclerViewtła wiersza:

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

Jednak jeśli doświadczasz problemy z tą metodą lub chcesz mieć lepszą kontrolę nad kolorami, możesz wykonać następujące czynności.

Niestandardowy efekt falowania

Ta odpowiedź zaczyna się od tego prostego przykładu RecyclerView systemu Android . Będzie wyglądać jak na poniższym obrazku.

Przykład efektu marszczenia GIF

Dodaj selektor dla urządzeń starszych niż API 21

Przed API 21 (Android 5.0 Lollipop) kliknięcie RecyclerViewelementu zmieniło kolor tła (brak efektu tętnienia). To też będziemy robić. Jeśli nadal masz użytkowników z tymi urządzeniami, są oni przyzwyczajeni do takiego zachowania, więc nie będziemy się o nich zbytnio martwić. (Oczywiście, jeśli naprawdę chcesz również dla nich efektu ripple, możesz użyć własnej biblioteki ).

Kliknij res/drawablefolder prawym przyciskiem myszy i wybierz opcję Nowy> Plik zasobów do rysowania . Nazwij to custom_ripple. Kliknij OK i wklej następujący kod.

custom_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorAccent" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</selector>

Użyłem colorAccentjako koloru podświetlenia dla stanu wciśniętego, ponieważ był już dostępny, ale możesz zdefiniować dowolny kolor.

Dodaj efekt falowania dla urządzeń API 21+

Kliknij res/drawablefolder prawym przyciskiem myszy i wybierz opcję Nowy> Plik zasobów do rysowania . Zadzwoń custom_rippleponownie. Nie klikaj OK, ale tym razem. Z listy Dostępne kwalifikatory wybierz opcję Wersja , a następnie kliknij przycisk >> i wpisz 21poziom platformy API . Teraz kliknij OK i wklej następujący kod.

v21 / custom_ripple.xml

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

    <item
        android:id="@android:id/mask"
        android:drawable="@android:color/white" />
</ripple>

Znowu użyłem colorAccent koloru tętnienia, ponieważ był dostępny, ale możesz użyć dowolnego koloru. Maska ogranicza efekt tętnienia tylko do układu wierszy. Najwyraźniej kolor maski nie ma znaczenia, więc użyłem nieprzezroczystej bieli.

Ustaw jako tło

W układzie głównym elementu RecyclerView ustaw tło na niestandardowe tętnienie, które utworzyliśmy.

android:background="@drawable/custom_ripple"

W przykładowym projekcie , od którego zaczynaliśmy, wygląda to tak:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@drawable/custom_ripple"
    android:padding="10dp">

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

</LinearLayout>

Skończone

Otóż ​​to. Teraz powinieneś być w stanie uruchomić swój projekt. Dzięki tej odpowiedzi i temu filmowi na YouTube za pomoc.

Suragch
źródło
Jeśli chcesz mieć domyślny kolor tła, po prostu usuń wiersz „android: id =" @ android: id / mask ", a następnie ustaw kolor elementu do rysowania na dowolny.
Jordan Hochstetler
26

Myślę, że brakuje jednego małego szczegółu.

Jeśli po dodaniu nadal nie widać efektu tętnienia, android:background="?android:attr/selectableItemBackground"spróbuj dodać następujące wiersze w katalogu głównym układu.

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

Zapewnią one klikalność widoku i umożliwią efekt ripple z atrybutem tła wspomnianym powyżej

Sriram R
źródło
5

dodaj te wiersze w widoku głównym xml adaptera

android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
Gundu Bandgar
źródło
2

Prostym i niestandardowym podejściem jest ustawienie motywu widoku, jak opisano tutaj .

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>

Inne niestandardowe implementacje można znaleźć tutaj .

Adam Hurwitz
źródło
1

Używanie stylu przycisku

To działało dla mnie niezliczoną ilość razy.

Dodaj styl przycisku bez obramowania do elementu głównego układu. Nie ma potrzeby stosowania atrybutów focusableani clickableatrybutów, domyślny styl obejmuje to wszystko za Ciebie.

<androidx.constraintlayout.widget.ConstraintLayout
    style="@android:style/Widget.Material.Button.Borderless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
Felix Favor Chinemerem
źródło
@ededede Możesz użyć atrybutów min-height, max-height, width ... XML, aby dostosować go do swoich upodobań.
Felix Favor Chinemerem