Rafael Nascimento
Rafael Nascimento

Reputation: 715

RecyclerView + CardView + Touch feedback

Has anybody solved the mystery of the CardView without touch feedback when it's inside a RecyclerView?

I have a RecyclerView with a bunch of CardViews (a CardList). When I click on any CardView, I start another Activity. That's working pretty fine, but I can't see any touch feedback when I click on the CardView.

Just in time, I've already configured my CardView (XML) with these:

android:clickable="true"
android:background="?android:selectableItemBackground"

Thanks!

Upvotes: 24

Views: 14699

Answers (5)

David Miguel
David Miguel

Reputation: 14450

Solution 1

As @Eugen proposed, you can make the layout inside CardView clickable, so then you can use android:background:

<android.support.v7.widget.CardView
    ...
    android:clickable="true"
    android:background="?attr/selectableItemBackground">

Solution 2

If you don't want to lose the item click listener by making the layout inside CardView clickable, you can use android:foreground:

<android.support.v7.widget.CardView
    ...
    android:clickable="true"
    android:foreground="?attr/selectableItemBackground">

Extra: you can use "?attr/selectableItemBackgroundBorderless" instead of "?attr/selectableItemBackground" if you don't want the rectangle mask.

Upvotes: 8

vikas kumar
vikas kumar

Reputation: 11018

Both Approach should work the same way.

1) If you want cardview to respond to touch feedback then use this one in cardview.

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

but if above approach is not working then you can set this property on child view group (Linear/Relative etc) of cardview.

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

But then itemView of ViewHolder will not respond to the touch event. since its been consumed by child view so you have to set clicklistener on childview to work on further with listener in recyclerview adapter, this way we can enable touch as well as click events on row items of recyclerview in our adapter.

if you have hard time following the touch and click on views in cardview with ripple then this might be helpful. Touch Feedback Problem

2.) The second approach is to use the traditional way of using custom touch selector drawable and set as background.

    <?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your ripple color">
    <item>
    <selector>
        <item android:state_selected="true">
            <color android:color="your selected color" />
        </item>
        <item android:state_activated="true">
            <color android:color="your selected color" />
        </item>
        <item>
            <color android:color="your normal color" />
        </item>
    </selector>
    </item>
</ripple>

Docs Ripple Drawable

Upvotes: 1

Volodymyr Kulyk
Volodymyr Kulyk

Reputation: 6546

Add foreground attribute:

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

Upvotes: 1

Gilang
Gilang

Reputation: 11

create selector "drawable/card_foreground_selector"

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#18000000"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
</selector>

and create "drawable/card_foreground.xml" (you'll need to tweak inset values according to elevation of your card)

<inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/card_foreground_selector"
android:insetLeft="2dp"
android:insetRight="2dp"
android:insetTop="3dp"
android:insetBottom="3dp"/>

modify your item (item.xml)

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:contentPadding="8dp"
    android:foreground="@drawable/card_foreground">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    // ..

    </LinearLayout>
</android.support.v7.widget.CardView>

you can view original post here

Upvotes: 1

Eugen Pechanec
Eugen Pechanec

Reputation: 38233

Background:

The CardView ignores android:background in favor of app:cardBackground which can only be color. The border and shadow are in fact part of the background so you cannot set your own.

Solution:

Make the layout inside the CardView clickable instead of the card itself. You already wrote both attributes needed for this layout:

android:clickable="true"
android:background="?android:selectableItemBackground"

Upvotes: 41

Related Questions