Adding Ripple Effect to RecyclerView item

87,330

Solution 1

I figured out. The only thing that I had to do is to add this attribute:

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

to the root element of the layout that my RecyclerView adapter inflates like that:

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

Result:

enter image description here

If you are still not able to see ripple effect, add these lines also to the root element of the layout.

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

Solution 2

As already answered, the simplest solution is to just add one of the following as your RecyclerView row's background:

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

However if you are experiencing problems with this method or if you want finer control over the colors, then you can do the following.

Custom Ripple Effect

This answer is starting with this simple Android RecyclerView example. It will look like the following image.

Ripple effect example GIF

Add selector for pre API 21 devices

Before API 21 (Android 5.0 Lollipop), clicking a RecyclerView item just changed its background color (no ripple effect). That is what we are going to do, too. If you still have users with those devices, they are used to that behavior, so we aren't going to worry about them too much. (Of course, if you really want the ripple effect for them, too, you could use a custom library.)

Right click your res/drawable folder and choose New > Drawable resource file. Call it custom_ripple. Click OK and paste in the following code.

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>

I used colorAccent as the highlight color for the pressed state because it was already available, but you can define whatever color you want.

Add Ripple Effect for API 21+ devices

Right click your res/drawable folder and choose New > Drawable resource file. Call it custom_ripple again. Don't click OK, yet this time, though. From the Available qualifiers list choose Version, then click the >> button and write 21 for the Platform API level. Now click OK and paste in the following code.

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>

Again, I used colorAccent for the ripple color because it was available, but you can use whatever color you want. The mask confines the ripple effect to just the row layout. The mask color apparently doesn't matter so I just used an opaque white.

Set as the background

In your RecyclerView item's root layout, set the background to the custom ripple that we created.

android:background="@drawable/custom_ripple"

In the example project that we started with, it looks like this:

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

Finished

That's it. You should be able to run your project now. Thanks to this answer and this YouTube video for help.

Solution 3

I think there is one small detail that is missed.

If you still do not get the ripple effect after adding android:background="?android:attr/selectableItemBackground" try adding these following lines in the root of the layout.

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

These will make sure that the view is clickable and will enable the ripple effect with the background attribute mentioned above

Solution 4

add this lines in your adapter xml root view

android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"

Solution 5

A simple and custom approach is to set a view theme as outlined here.

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>

Other custom implementations may be found here.

Share:
87,330
Georgi Koemdzhiev
Author by

Georgi Koemdzhiev

I like programming, it's a passion. I work with different technologies like ASP.NET Core, Flutter and AWS. AWS Certified Developer – Associate

Updated on May 27, 2020

Comments

  • Georgi Koemdzhiev
    Georgi Koemdzhiev about 4 years

    I am trying to add Ripple Effect to RecyclerView's item. I had a look online, but could not find what I need. I assume it has to be a custom effect. I have tried android:background attribute to the RecyclerView itself and set it to "?android:selectableItemBackground" but it did not work.:

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

    This is the RecyclerView that I am trying to add the effect to:

    enter image description here

    • Suragch
      Suragch about 6 years
      I'm reopening this as not a duplicate of this question. Although the solutions may be similar, there are certain aspects of a having a CardView in that question than do not pertain to this more general question.
    • Georgi Koemdzhiev
      Georgi Koemdzhiev about 6 years
      @Suragch Thank you for noticing the difference :)
  • Nabin
    Nabin over 8 years
    What if the root element is CardView?
  • Sanved
    Sanved over 8 years
    @SpiderMan You should write your code inside a Relative or a Linear Layout and then place it inside the Card Layout.
  • Vamsi Challa
    Vamsi Challa over 8 years
    @pronoobsanved, this helped me! For those who are still facing the problem, CardView takes a single layout as a child. For that child, set clickable, focusable as true and background as ?attr/selectedableItemBackground
  • Sanved
    Sanved over 8 years
    glad I could help.
  • Lorne Laliberte
    Lorne Laliberte about 8 years
    @NabinKhadka for a CardView set it as the foreground instead, i.e. android:foreground="?android:attr/selectableItemBackground"
  • Safeer
    Safeer about 7 years
    By using this solution, only ripple effect works. Custom background is not working.
  • Georgi Koemdzhiev
    Georgi Koemdzhiev about 7 years
    I guess, it does not. I have not tested it with a custom background
  • Joaquin Iurchuk
    Joaquin Iurchuk almost 7 years
    I had to add the option android:clickable="true" also to make this work
  • mrid
    mrid almost 7 years
    How to use this if I want a custom background ??
  • Georgi Koemdzhiev
    Georgi Koemdzhiev almost 7 years
    @mrid This should help codexpedia.com/android/…
  • Hardik Parmar
    Hardik Parmar over 4 years
    @GeorgiKoemdzhiev Hey I try out this but its not working.
  • Jordan Hochstetler
    Jordan Hochstetler about 4 years
    If you want to have a default background color just remove the 'android:id="@android:id/mask' line and then set the color of the drawable to whatever you want.
  • Favour Felix Chinemerem
    Favour Felix Chinemerem almost 4 years
    @ededede You can use the min-height, max-height, width...XML attributes to tweak it to your taste.