Android-L CardView Visual Touch Feedback
API 11+:
Add android:foreground="?android:attr/selectableItemBackground"
to your CardView
element.
API 9+:
Add android:foreground="?selectableItemBackground"
to your CardView
element.
Edit: The ripple originating from the center and not from the touch point is a known bug, and has been fixed.
RecyclerView + CardView + Touch feedback
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"
CardView lift on touch
Try wrapping the animator resource with <set>
.
<?xml version="1.0" encoding="utf-8"?>
<set>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
android:state_pressed="true">
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="6dp"
android:valueType="floatType" />
</set>
</item>
<item>
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="0"
android:valueType="floatType" />
</set>
</item>
</selector>
</set>
CardView's background which will respond to android:state_selected and android:state_pressed
After experimenting for quite some time, I can pretty much conclude that this is limitation of current CardView
- https://code.google.com/p/android/issues/detail?id=78198
Don't use CardView
's foreground workaround. Although it is widely being proposed, it just don't work!
My suggestion is, avoid using CardView
if you need a customized selector. Replace it LayerDrawable
. Here's what I had done.
card.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="#ffededed" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke
android:width="1dp"
android:color="#ffe8e8e8" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke
android:width="1dp"
android:color="#ffe1e1e1" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffdbdbdb" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffd5d5d5" />
<corners android:radius="2dp" />
</shape>
</item>
<!--
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffcfcfcf" />
<corners android:radius="2dp" />
</shape>
</item>
-->
<item>
<shape >
<solid android:color="#ffffffff" />
<corners android:radius="2dp" />
</shape>
</item>
</layer-list>
card_selected.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke
android:width="1dp"
android:color="#ffededed" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke
android:width="1dp"
android:color="#ffe8e8e8" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke
android:width="1dp"
android:color="#ffe1e1e1" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffdbdbdb" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffd5d5d5" />
<corners android:radius="2dp" />
</shape>
</item>
<!--
<item>
<shape>
<padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
<stroke
android:width="1dp"
android:color="#ffcfcfcf" />
<corners android:radius="2dp" />
</shape>
</item>
-->
<item>
<shape>
<solid android:color="#ffffe1b3" />
<stroke
android:width="1px"
android:color="#fff76d3c" />
<corners android:radius="2dp" />
</shape>
</item>
</layer-list>
statelist_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_pressed="true" android:drawable="@drawable/card_selected" /> <!-- pressed -->
<item android:state_selected="true" android:drawable="@drawable/card_selected" /> <!-- pressed -->
<item android:drawable="@drawable/card" />
</selector>
layout.xml
<!-- A CardView that contains a TextView -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@drawable/statelist_item_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >
<TextView
android:id="@+id/txt_label_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
tools:text="Item Number One" />
<TextView
android:id="@+id/txt_date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="Item Number One" />
</LinearLayout>
You will get the pretty nice outcome.
Ripple Effect on androidx.cardview.widget.CardView
Don't use any background/foreground
in CardView
. If you use any background color then, then just add app:cardBackgroundColor="@color/cardBackgroundColor
. Remove any padding
from the CardView
. Use margin
for space between items.
Now, for the ripple effect in CardView
, just add an immediate child layout in your CardView
. Set android:background="?attr/selectableItemBackground"
in the child layout. Add any necessary padding/margin
in the child if you need.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/tools"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
card_view:cardCornerRadius="6dp"
card_view:cardElevation="4dp"
card_view:cardMaxElevation="6dp"
app:ignore="NamespaceTypo">
<!-- Child Layout -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="?attr/selectableItemBackground"
android:orientation="vertical">
<!-- Your content here -->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Making entire cardview clickable
Just a thought if more elegant solutions could not be found: you may try overriding onInterceptTouchEvent()
for the cardview
and use a gesture detector which listens for a tap up on the motion event intercepted. Return true
if the gesture is detected, such that the MotionEvent is intercepted and not passed on to its children, including the listview.
This way the cardview
could see the click event before the listview
.
Add selectableItemBackground to CardView
The issue was that I used the same Drawable with multiple Cards.
You have to retrieve a new Drawable for each Card.
More details in this answer.
Related Topics
How to to Check If a User Has Rated Your App on the Google Play
Android - Running a Method Periodically Using Postdelayed() Call
How to Change Style of a Default Edittext
How to Read CPU Frequency on Android Device
Android Manifest Restrict to Tablets
Android - How to Get Application Name? (Not Package Name)
Android Studio: Creating Landscape Layouts
Editing Functionality of Host Card Emulation in Android
Android Background Drawable Not Working in Button Since Android Studio 4.1
How to Add External Fonts to Android Application
Remove Vertical Padding from Horizontal Progressbar
How to Instantiate Application Com.Android.Tools.Fd.Runtime.Bootstrapapplication Android
Fitssystemwindows Effect Gone for Fragments Added via Fragmenttransaction