Search code examples
androidandroid-recyclerviewandroid-cardviewripple-effect

Setting Ripple effect to RecyclerView CardView item without having to double tap for an item action


I have a RecyclerView with a CardView as the root element of the row item layout. I managed to have a ripple effect to CardView using below list item layout as described here.

Row item layout:

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/margin_8dp"
    android:background="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:foreground="?android:attr/selectableItemBackground"
    app:cardBackgroundColor="@color/cyan"
    app:cardCornerRadius="20dp"
    app:cardElevation="5dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/transparent"
        android:padding="@dimen/margin_8dp">

            <!-- Underlying views-->

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

The problem is that to have a click action on a row item in the RecyclerView adapter requires a couple of taps, the first tap for selecting the item and showing the ripple effect, and the second tap for the actual click to trigger View.OnClickListener.

Using android:focusableInTouchMode = "true" attribute in CardView is the reason for the double tap; but disabling it, also disable the ripple effect consequently.

I tried to use a custom Ripple effect as in this answer, but doesn't work. Also tried to have the ripple effect on the underlying CardView root element as in this answer, but still nothing new.

Similar thing for using the button style as in here.

And I have a transnational itemView click listener in RecyclerView adapter within the view holder

class ViewHolder extends RecyclerView.ViewHolder {

    ViewHolder(@NonNull final View itemView) {
        super(itemView);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
     }
}

Solution

  • I solved this by totally removing android:focusableInTouchMode = "true" & android:foreground from the CardView, and adding the ripple effect to the root item within the CardView with android:background="?android:attr/selectableItemBackground"

    <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/margin_8dp"
        app:cardBackgroundColor="@color/cyan"
        app:cardCornerRadius="20dp"
        app:cardElevation="5dp">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?android:attr/selectableItemBackground"
            android:padding="@dimen/margin_8dp">
    
                <!-- Underlying views-->
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    </androidx.cardview.widget.CardView>