246

I'm trying to get a CardView to display the ripple effect when touched by setting the android:backgound attribute in the activity XML file as described here on the Android Developers page, but it isn't working. No animation at all, but the method in onClick is called. I've also tried creating a ripple.xml file as suggested here, but same result.

The CardView as it appears in the activity's XML file:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="155dp"
    android:layout_height="230dp"
    android:elevation="4dp"
    android:translationZ="5dp"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:onClick="showNotices"
    android:background="?android:attr/selectableItemBackground"
    android:id="@+id/notices_card"
    card_view:cardCornerRadius="2dp">

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

I'm relatively new to android development, so I might have made a few obvious mistakes.

Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
AkraticCritic
  • 2,595
  • 2
  • 12
  • 11

14 Answers14

737

You should add following to CardView:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Uniruddh
  • 4,427
  • 3
  • 52
  • 86
Jaden Gu
  • 9,143
  • 3
  • 23
  • 26
  • 10
    Works on lollipop with ripple effect but only gives solid color when run on older platforms. Good enough for me :) – mach Feb 17 '15 at 09:11
  • if added to CardView works flawlessly even on older android versions (maybe support libraries got updated?) – Gianluca P. Apr 03 '15 at 11:48
  • 21
    A little observation: I noted that the clickable attribute is not necessary and even can break some things! I had a a GridView filled with clickable CardViews and the listener was not properly working. I removed the clickable tag from the XML and everything now works flawlessly – Joaquin Iurchuk Apr 27 '15 at 14:43
  • 2
    @joaquin without the clickable, it causes the the ripple to originate from the center only – frostymarvelous Jun 19 '15 at 18:43
  • Can you give some explanation as said by @sashoalm where to place this code? – Pratik Butani Sep 14 '15 at 13:10
  • 2
    `?android:attr/selectableItemBackground` requires API level 11 – Pratik Butani Sep 14 '15 at 13:11
  • @PratikButani just out the two lines in the xml of your CardView file. – Jaden Gu Sep 15 '15 at 03:34
  • @frostymarvelous Why doesn't the ripple start from the touch point & start from the center. – Srikar Reddy Feb 01 '16 at 15:54
  • 1
    @SrikarReddy Not entirely certain. JUst an observation I made in my tests. – frostymarvelous Feb 01 '16 at 17:08
  • 2
    There should really be a system in SO whereby the users can override the accepted answer. – LukeWaggoner Apr 08 '16 at 04:35
  • @Jerry Gu Just out of curiosity, how to delay (actions like ui dialogues which hides ripple effect behind it) ui dialogues, so that ripple effect is displayed? I don't want to use handler. – AskQ May 15 '17 at 13:15
  • 1
    @AskQ I think you can find what you want here: http://stackoverflow.com/questions/30201422/have-a-button-execute-onclicklistener-on-end-of-ripple-animationmaterial-theme – Jaden Gu May 16 '17 at 04:23
  • 1
    on api 17 if you just tap it has no effect, works only if you make your tap from little bit longer to long press. – temirbek Aug 10 '17 at 13:41
  • 13
    Working without `android:clickable="true"`. – Sean Mar 13 '18 at 09:07
  • If you have `RelativeLayout` or `LinearLayout` etc. as the single child, make it `clickable="false"` so it will pass the click event to the `CardView` below it – osrl Sep 25 '18 at 12:06
  • 11
    for CardView better use`?attr/selectableItemBackgroundBorderless` – Danylo.Vus Oct 31 '18 at 14:34
  • I've found that if you press the cardView quite quickly then you don't even see any ripple animation; the ripple animation seems to require a 1sec touch event in order to see anything. It seems like I have to add postDelayed() call to run my click-event action after 1 sec and force the animation to show for that 1 sec ! – Someone Somewhere Aug 13 '19 at 22:27
  • 1
    Hi there, is there any way to change the color of ripple if I use the above shown solution? Thanks! – Mark Delphi Dec 20 '19 at 08:28
  • if you add the above code you may get a warning at focussable so add ````android:focusable="true"````this focusable is added to define whether this view is focussable. – Vatsal kesarwani Dec 14 '20 at 14:06
  • Thanks man. but it works without {android:clickable="true"} – Annas Bin Waheed Jun 05 '21 at 16:37
  • @Sean not always. ?attr/selectableItemBackgroundBorderless doesnot work without android:clickable="true" – Kirguduck Feb 22 '22 at 16:21
32

I managed to get the ripple effect on the cardview by :

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:clickable="true" 
    android:foreground="@drawable/custom_bg"/>

and for the custom_bg that you can see in above code, you have to define a xml file for both lollipop(in drawable-v21 package) and pre-lollipop(in drawable package) devices. for custom_bg in drawable-v21 package the code is:

<ripple 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
<item
    android:id="@android:id/mask"
    android:drawable="@android:color/white"/>
</ripple>

for custom_bg in the drawable package, code is:

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

<item android:state_pressed="true">
    <shape>
        <solid android:color="@color/colorHighlight"></solid>
    </shape>
</item>
<item>
    <shape>
        <solid android:color="@color/navigation_drawer_background"></solid>
    </shape>
</item>
</selector>

so on pre-lollipop devices you will have a solid click effect and on lollipop devices you will have a ripple effect on the cardview.

Sergii
  • 1,521
  • 3
  • 24
  • 37
Rahul Ahuja
  • 812
  • 10
  • 24
  • 2
    Hi, I realize by applying selector (or ripple) on CardView's foreground, it will block children in CardView itself - http://stackoverflow.com/questions/33763403/cardviews-background-which-will-respond-to-androidstate-selected-and-androids May I know do you encounter the same prob as I did? Or, do I miss out anything? Thanks. – Cheok Yan Cheng Nov 18 '15 at 03:13
  • @CheokYanCheng : I am not facing any such issue as your's but i would say from personal experience that cardView has some bugs for pre-lollipop. Avoid using cardview:elevation property in pre-lollipop. The above works fine for me and other upvotes. – Rahul Ahuja Nov 18 '15 at 06:51
  • May I know, what is the value of your colorHighlight & navigation_drawer_background. If you used your own defined color without transparency, can you still see your card's children? – Cheok Yan Cheng Nov 18 '15 at 09:32
  • @CheokYanCheng : values are as, #FFFFFF #FF8A65 – Rahul Ahuja Nov 18 '15 at 10:41
  • I don't work for my case. I use your selector as foreground. As expected, solid white color (navigation_drawer_background), which is used as card view foreground will block the visibility of all children - http://i.imgur.com/CleYh5B.png This is how it look like without applying selector as foreground - http://i.imgur.com/ZXk5Aoq.png – Cheok Yan Cheng Nov 18 '15 at 15:07
  • did u create the package right? As explained above.. @CheokYanCheng – Rahul Ahuja Nov 19 '15 at 05:39
  • you have. to preset the height of card view and set mlatch_parent inside – Jeff Bootsholz Jan 22 '18 at 08:16
15

The ripple effect was omitted in the appcompat support library which is what you're using. If you want to see the ripple use the Android L version and test it on an Android L device. Per the AppCompat v7 site:

"Why are there no ripples on pre-Lollipop? A lot of what allows RippleDrawable to run smoothly is Android 5.0’s new RenderThread. To optimize for performance on previous versions of Android, we've left RippleDrawable out for now."

Check out this link here for more info

Developer Paul
  • 1,502
  • 2
  • 13
  • 18
  • That would be it. Thanks! – AkraticCritic Nov 15 '14 at 04:35
  • 40
    But how would you put ripple effect on cardView for Android Lollipop then? – android developer Dec 01 '14 at 09:10
  • So I have to decide between backward compatibility using appcompat or having all the new effects, using classes from android core but limiting myself to API 21? – Urs Reupke Dec 01 '14 at 12:51
  • You could make 2 APK's one for 21+ and the other for < 21. Or divide the code since 21+ won't be using supportActionbar etc. Might sound like a lot of trouble, but that's your sollution I believe. – Mathijs Segers Dec 23 '14 at 15:06
  • 1
    This is why writing "pure" Android L applications is not viable at the moment. As of July 2015 you will be targeting 12% of the Android user base. – Glenn Bech Jul 14 '15 at 08:17
15

If the app minSdkVersion which you are working is level 9, you can use:

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

Instead, starting from level 11, you use:

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

From documentation:

clickable - Defines whether this view reacts to click events. Must be a boolean value, either "true" or "false".

foreground - Defines the drawable to draw over the content. This can be used as an overlay. The foreground drawable participates in the padding of the content if the gravity is set to fill.

Community
  • 1
  • 1
Filipe Brito
  • 5,329
  • 5
  • 32
  • 42
12

Use Material Cardview instead, it extends Cardview and provides multiple new features including default clickable effect :

<com.google.android.material.card.MaterialCardView>

...

</com.google.android.material.card.MaterialCardView>

Dependency (It can be used up to API 14 to support older device):

implementation 'com.google.android.material:material:1.0.0'
Ankit Gupta
  • 512
  • 1
  • 6
  • 19
  • 1
    You are right. Don't forget add android:clickable="true" and android:focusable="true" – Burak Dizlek Aug 07 '20 at 21:11
  • @BurakDizlek why do we need `clickable` and `focusable` attributes? I see no difference when using `` – Andy Jul 24 '22 at 03:04
  • 1
    @andy I guess, if you have set setonclicklistener on your card, then it is not needed else if you want the ripple effect without setonclicklistener then add it in ur xml. – Ankit Gupta Jul 24 '22 at 11:59
7

For me, adding the foreground to CardView didn't work (reason unknown :/)

Adding the same to it's child layout did the trick.

CODE:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:focusable="true"
    android:clickable="true"
    card_view:cardCornerRadius="@dimen/card_corner_radius"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:id="@+id/card_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="?android:attr/selectableItemBackground"
        android:padding="@dimen/card_padding">

    </LinearLayout>
</android.support.v7.widget.CardView>
Prabs
  • 4,923
  • 6
  • 38
  • 59
  • 2
    That is because the child intercepts the event, if you try something like adding padding to the cardview (something like 20dp), and you click on the part where the padding would be, then you'll see the ripple effect even without the child having the foreground attribute set – Cruces Feb 08 '18 at 10:40
  • 1
    This worked for me as well, using the new Material Components: com.google.android.material.card.MaterialCardView. I had an elevation stateListAnimator for the card view to adjust elevation and the ripple applied to the inner constraint layout with selectable item background in foreground without clickable attribute. – Patty P Aug 02 '18 at 14:28
  • I don't remember it now, but there is a way to set the child views not to react to the click event – Someone Somewhere Aug 13 '19 at 22:32
7

Add these two like of code work like a charm for any view like Button, Linear Layout, or CardView Just put these two lines and see the magic...

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Hitesh Kushwah
  • 1,351
  • 13
  • 23
3

Add the following to your xml:

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

And add to your adapter (if it's your case)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val attrs = intArrayOf(R.attr.selectableItemBackground)
            val typedArray = holder.itemView.context.obtainStyledAttributes(attrs)
            val selectableItemBackground = typedArray.getResourceId(0, 0)
            typedArray.recycle()

            holder.itemView.isClickable = true
            holder.itemView.isFocusable = true
            holder.itemView.foreground = holder.itemView.context.getDrawable(selectableItemBackground)
        }
    }
Mateus Nascimento
  • 815
  • 10
  • 11
2

Ripple event for android Cardview control:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:foreground="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:layout_marginBottom="4dp"
    android:layout_marginTop="4dp" />
Edric
  • 24,639
  • 13
  • 81
  • 91
chavanNil
  • 161
  • 2
  • 4
2

If there is a root layout like RelativeLayout or LinearLayout which contain all of the adapter item's component in CardView, you have to set background attribute in that root layout. like:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="122dp"
android:layout_marginBottom="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
card_view:cardCornerRadius="4dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/touch_bg"/>
</android.support.v7.widget.CardView>
Robert Lee
  • 21
  • 2
2

For those searching for a solution to the issue of the ripple effect not working on a programmatically created CardView (or in my case custom view which extends CardView) being shown in a RecyclerView, the following worked for me. Basically declaring the XML attributes mentioned in the other answers declaratively in the XML layout file doesn't seem to work for a programmatically created CardView, or one created from a custom layout (even if root view is CardView or merge element is used), so they have to be set programmatically like so:

private class MadeUpCardViewHolder extends RecyclerView.ViewHolder {
    private MadeUpCardView cardView;

    public MadeUpCardViewHolder(View v){
        super(v);

        this.cardView = (MadeUpCardView)v;

        // Declaring in XML Layout doesn't seem to work in RecyclerViews
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            int selectableItemBackground = typedArray.getResourceId(0, 0);
            typedArray.recycle();

            this.cardView.setForeground(context.getDrawable(selectableItemBackground));
            this.cardView.setClickable(true);
        }
    }
}

Where MadeupCardView extends CardView Kudos to this answer for the TypedArray part.

Breeno
  • 3,007
  • 2
  • 31
  • 30
  • 1
    Thanks for this answer. In my case I made it working by setting only clickable and focusable to true programmatically, it started showing ripple effect on my custom view (parent of the view is MaterialCardView) – intips Mar 20 '21 at 23:51
1

I wasn't happy with AppCompat, so I wrote my own CardView and backported ripples. Here it's running on Galaxy S with Gingerbread, so it's definitely possible.

Demo of Ripple on Galaxy S

For more details check the source code.

Edric
  • 24,639
  • 13
  • 81
  • 91
Zielony
  • 16,239
  • 6
  • 34
  • 39
1
  android:foreground="?android:attr/selectableItemBackgroundBorderless"
   android:clickable="true"
   android:focusable="true"

Only working api 21 and use this not use this list row card view

Tarun Umath
  • 900
  • 10
  • 7
0

If you want any elements inside (Childeren) the Card view you can use:

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

but if you need whole of Card view, do like this:

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

If you use both of them, the color will be darker than the rest.

However, the easiest way is

com.google.android.material.card.MaterialCardView
Mori
  • 2,653
  • 18
  • 24