151

How can I have a ripple effect in a simple linear/relative layout when touching the layout?

I've tried setting the background of a layout to something like:

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

    <item android:drawable="@android:color/white"/>

</ripple>

However I'm only seeing a plain white background and no ripple effect when touching the layout. What am I doing wrong?

Edit:

For reference, here is my layout xml file:

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:background="@drawable/test"
        android:clickable="true">
    </RelativeLayout>
Zach
  • 3,909
  • 6
  • 25
  • 50
  • 2
    The view hosting the ripple needs to be enabled and clickable or focusable. – alanv Nov 19 '14 at 00:09
  • Thanks Alanv, see below for my response. Basically I am marking my layout I want to have the ripple effect in as clickable, but it does not work still. – Zach Nov 19 '14 at 20:02
  • Also, this works fine if I remove the `` section. So I'm not sure how this is supposed to work if I wanted a background color on the layout. Laying this on top of another layout with a background color also does not work! – Zach Nov 19 '14 at 20:36
  • 4
    What color is the ripple being drawn in your view, e.g. what color does colorControlHighlight resolve to? – alanv Nov 20 '14 at 00:36

11 Answers11

325

Set these properties on your layout (if your layout has the default white/light background):

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

You don't need a custom drawable in this case.

However, if your layout has a black/dark background, you'd have to create your own ripple drawable like this one:

<?xml version="1.0" encoding="utf-8"?>
<!-- An white rectangle ripple. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@android:color/white">
    <item
        android:id="@android:id/mask"
        android:gravity="center">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white"/>
        </shape>
    </item>
</ripple>

And then set this ripple drawable as your android:background property.

You can see many examples of these types of ripples in AOSP: in here

Tupio
  • 432
  • 7
  • 19
IgorGanapolsky
  • 26,189
  • 23
  • 116
  • 147
  • 13
    what if i have to give different color as background ? Then what should be the best approach ? – Anuj Sharma Apr 08 '16 at 12:08
  • 2
    @AnujSharma Have you tried giving color resource for `background`? – IgorGanapolsky Apr 08 '16 at 12:45
  • yes i tried that, in case i need to add ripple xml in drawable folder, i thought i can use this single line to generate ripple effect – Anuj Sharma Apr 08 '16 at 15:34
  • 1
    @ralphspoon See http://stackoverflow.com/questions/26604134/how-to-achieve-ripple-animation-using-support-library – IgorGanapolsky May 16 '16 at 13:08
  • 1
    @AnujSharma you can create a drawable with color and ripple efect and give it as a background to your layout. – Erfan GLMPR Aug 16 '16 at 20:17
  • 36
    If you'd like another background color you can set that color as background and put "?attr/selectableItemBackground" as android:foreground instead – Lucas Arrefelt Aug 31 '16 at 11:02
  • @IgorGanapolsky now the error has gone but no ripple. nothing happens when I click – TSR Oct 03 '16 at 19:49
  • 1
    Keep in mind you also have the option to use android:background="?attr/selectableItemBackgroundBorderless" With it being border less The ripple effect will extend out to the parent view. This may look better in many cases. – Michael Kern Nov 02 '18 at 01:27
  • Beware that the `foreground` attribute has been added in API 23 (Android 6.0) and `has no effect on API levels lower than 23` (as per Android Studio warning) – Mickäel A. Mar 16 '20 at 16:12
  • @flawyte Correct, however the `foreground` attribute is available on a `FrameLayout` below API v23, I think down to v16. – Matt Mc May 17 '20 at 05:40
  • @MattMc I believe it's been available on `FrameLayout` since API 1, however there's a [better solution](https://stackoverflow.com/a/61202414/1276306) than wrapping your `ImageView` in an additional container just to add a ripple. – Mickäel A. May 18 '20 at 08:53
69

I'm adding this in addition to Igor Ganapolsky's answer in case anyone wants to have a layout with different color and also have a ripple effect. You simply create a ripple effect in drawables like this:

ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/rippleColor"
    tools:targetApi="lollipop"> <!-- ripple effect color -->
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <solid android:color="@color/backgroundColor" /> <!-- background color -->
        </shape>
    </item>
</ripple>

then give it as your layout's background or any button as Igor Ganapolsky mentioned in his answer.

android:clickable="true"
android:background="@drawable/ripple"
Community
  • 1
  • 1
Erfan GLMPR
  • 958
  • 1
  • 12
  • 14
51

You have to alter following code snippet in any widget(TextView/Button) and you can implement Ripple Effect:

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

And you are good to go.

Pankaj Lilan
  • 4,245
  • 1
  • 29
  • 48
  • hmm foreground? this is great! – fullmoon Oct 16 '17 at 20:27
  • This is helpful if you already have a android:background="@color/colorAccent" set – aero Oct 25 '17 at 21:32
  • @aero It is helpful, even if you don't set any background. – Pankaj Lilan Jan 19 '18 at 04:59
  • 1
    this works on layouts and custom views in addition to widgets. – anoo_radha Aug 03 '18 at 17:51
  • Keep in mind you also have the option to use android:background="?attr/selectableItemBackgroundBorderless" With it being border less The ripple effect will extend out to the parent view. This may look better in many cases. – Michael Kern Nov 02 '18 at 01:27
  • 1
    @MichaelKern Yes, you're right, also it is based upon everybody's requirement in their code. – Pankaj Lilan Nov 02 '18 at 08:56
  • 3
    Beware that the `foreground` attribute has been added in API 23 (Android 6.0) and `has no effect on API levels lower than 23` (as per Android Studio warning) – Mickäel A. Mar 16 '20 at 16:12
  • @flawyte Correct, however the foreground attribute is available on a FrameLayout below API v23, I think down to v16. – Matt Mc May 17 '20 at 05:41
  • @MattMc I believe it's been available on `FrameLayout` since API 1, however there's a [better solution](https://stackoverflow.com/a/61202414/1276306) than wrapping your `ImageView` in an additional container just to add a ripple. – Mickäel A. May 18 '20 at 08:54
25

It turns out this is working as intended. The standard Material theme colorControlHighlight value is #40ffffff. So on a white background, this will not show up. Changing the highlight color to something else works, and/or changing the background color of the object.

Thanks all (especially Alanv for pointing me in the right direction).

Zach
  • 3,909
  • 6
  • 25
  • 50
  • if I'm using android:background="?attr/selectableItemBackground" on my view how can I change the background of the object? – codeskraps Nov 11 '15 at 16:50
  • 1
    Nevermind I found that the selectableItemBackground default state is transparent. So, I set a view under it with the color I wanted. – codeskraps Nov 11 '15 at 17:15
  • 1
    quick note: you can change `colorControlHighlight` in your `styles.xml`. Add it to your custom theme for instance. – Nuhman Oct 11 '18 at 07:38
15

This is an example for clicking on a sample layout with ripple effect :

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical">
Javid Sattar
  • 749
  • 8
  • 14
9

Set android:clickable="true" on your layout.

tomrozb
  • 25,773
  • 31
  • 101
  • 122
JeromePApp
  • 209
  • 1
  • 6
6
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#cfd8dc"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#d1c4e9" />
        </shape>
    </item>
</ripple>

Use this ripple.xml in Drawable folder, then assign it as View's

android:background="@drawable/ripple"

android:clickable="true"

Abhishek Sengupta
  • 2,938
  • 1
  • 28
  • 35
2

Simply add default ripple effect with android:background="?selectableItemBackground"

Like:

<LinearLayout
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="?selectableItemBackground"
            android:clickable="true"
            >

           ...

</LinearLayout>
yatin deokar
  • 730
  • 11
  • 20
0

Put this into your layout:

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

Note: There is a bug in API documentation. It will work only on API >= 23

For all API levels use this Solution

Community
  • 1
  • 1
  • 2
    Your link redirect this same page – TSR Oct 03 '16 at 19:14
  • Keep in mind you also have the option to use android:background="?attr/selectableItemBackgroundBorderless" With it being border less The ripple effect will extend out to the parent view. This may look better in many cases. – Michael Kern Nov 02 '18 at 01:27
0

I tries all those answers and nothing worked to me, so, I solved creating the following style:

<style name="Button.Borderless" parent="Base.Widget.AppCompat.Button.Borderless">
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
    <item name="android:layout_marginLeft">-6dp</item>
    <item name="android:layout_marginRight">-6dp</item>
    <item name="android:paddingTop">0dp</item>
    <item name="android:paddingBottom">0dp</item>
    <item name="android:paddingLeft">6dp</item>
    <item name="android:paddingRight">6dp</item>
</style>

And then, I applied to my linear layout:

<LinearLayout
      android:id="@+id/ll_my_ripple"
      style="@style/Button.Borderless">
</LinearLayout>
Ângelo Polotto
  • 8,463
  • 2
  • 36
  • 37
0

To make a circlar effect use the below code:

android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37