Search code examples
androidandroid-recyclerviewlistitemrippledrawable

Correctly setting the background of a list item


I use a RecyclerView and a simple item layout consisting of a ConstraintLayout holding the text elements of each item. I want to set the background of all items while

  1. showing a ripple effect when clicked.
  2. visualizing when the view is active.
  3. being able to set the colors. (optional, if it really has to be)

The minimum SDK version is 21 and is allowed to be raised if required.


What I tried:

  • Using @android:drawable/list_selector_background is not customizable and did not show a ripple.
  • Using ?selectableItemBackground or ?selectableItemBackgroundBorderless does not work, it throws an exception at runtime (Failed to resolve attribute [...]). I do have the design support library placed in my gradle script, or now the com.google.android.material package. Prepending android:attr/ produced the same error.
  • Using a StateListDrawable to build it all by myself using many <ripple> Drawables seemed overly complicated since I did not want to reproduce the whole functionality of above features.

Solution

  • This answer linked by @Cheticamp combined with the approach in this article worked fine:

    The layout of an item looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/list_item_background_active_handler">
    
        <include
            layout="@layout/the_actual_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?selectableItemBackground" />
    
    </FrameLayout>
    

    And the list_item_background_active_handler looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:drawable="@color/listBackgroundActive" android:state_activated="true" />
    
        <!-- default -->
        <item android:drawable="@android:color/transparent" />
    
    </selector>
    

    This allows for handling the active state with a custom color. Simply call isActivated(true) on the view of an item in onBindViewHolder() in the adapter.

    The color of the ripple effect can be customized with this approach.