160

Background

On the dialer app of Android, when you start searching for something, and you click the arrow button on the left of the EditText, you get a circular ripple effect on it :

enter image description here

The problem

I've tried to have it too, but I got a rectangular one:

    <ImageButton
        android:id="@+id/navButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="8dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/search_ic_back_arrow"/>

The question

How do I make the button have a circular ripple effect when being clicked? Do I have to create a new drawable, or is there a built in way for that?

android developer
  • 114,585
  • 152
  • 739
  • 1,270

13 Answers13

354

If you are using AppCompat theme, then you could set the background of the view as:

android:background="?selectableItemBackgroundBorderless"

This will add circular ripple on 21 and above and square background on below 21.

bond
  • 11,236
  • 7
  • 48
  • 62
123

Another attribute with round ripple effect, specially for action bar:

android:background="?actionBarItemBackground"

UPD: Ripple color can be changed by this attribute:

<!--somewhere in styles-->
<item name="colorControlHighlight">your_color_here</item>

But keep in mind, this attribute applies to all default ripple effects.

Anrimian
  • 4,257
  • 4
  • 22
  • 30
56

Create and set a ripple drawable as background. Something like this.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/grey_15">
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <solid android:color="?android:colorPrimary"/>
        </shape>
        <color android:color="@color/white"/>
    </item>
</ripple>
Etienne Lawlor
  • 6,817
  • 18
  • 77
  • 89
Thomas R.
  • 7,988
  • 3
  • 30
  • 39
  • It's something in my code. You can use your colors :) – Thomas R. Aug 11 '15 at 12:30
  • How would I use the default selector in case it's on pre-Lollipop ? Also, does it use the same colors as the one on the dialer? – android developer Aug 11 '15 at 12:32
  • 2
    You can put the ripple drawable in your drawables-v21 folder. And for pre L use a simple state drawable. Use the same file name and put it into the drawable (default) folder. – Thomas R. Aug 11 '15 at 12:35
  • I mean, what should it have for pre-Lollipop, inside its drawable file? Also, please answer about the color. Is it possible to use the same one that's used for "selectableItemBackground" ? – android developer Aug 11 '15 at 12:39
  • Ripple is not available in pre-lollipop. So in the drawable file of pre-lollipop, ordinary button drawable is needed. – capt.swag Aug 11 '15 at 12:40
  • 2
    You can also create a style. In values-v21 folder create a new style and set the ripple drawable as background. And for pre L, i.e. in your values folder styles.xml put as background the "selectableItemBackground" attribute for the same style. – Thomas R. Aug 11 '15 at 12:46
  • @ThomasR. Can you please show exactly what to put? Also, what's the value of "grey_15" ? – android developer Aug 16 '15 at 09:15
  • According to my tests, this works only if the button has a square shape (width==height). when it's not, I get an elliptic shape. I've even tried to set the size of the drawable with equal width and height, but I still get this issue. How come? – android developer Jan 05 '16 at 13:33
  • require api level 21 :) – Jithu P.S Sep 21 '16 at 06:03
  • 1
    If you want the same ripple color as the other default ripple effects used in the app, use "?attr/colorControlHighlight" as the color. – alexbchr Sep 20 '17 at 20:03
  • I recommend to change the shape from oval to rectangle and then within the shape add something like – Panther Dec 02 '21 at 14:25
45

Just Add this background to your view

"android:background=?android:attr/actionBarItemBackground"

Dipakk Sharma
  • 976
  • 1
  • 8
  • 11
31

If you already have a background image, here is an example of a ripple that looks close to selectableItemBackgroundBorderless:

            <ImageButton
                android:id="@+id/btn_show_filter_dialog"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:background="@drawable/ic_filter_state"/>

ic_filter_state.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_pressed="true"
        android:state_enabled="true"
        android:drawable="@drawable/state_pressed_ripple"/>
    <item
        android:state_enabled="true"
        android:drawable="@drawable/ic_filter" />
</selector>

state_pressed_ripple.xml: (opacity set to 10% on white background) 1AFFFFFF

 <?xml version="1.0" encoding="UTF-8"?>    
    <ripple xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="oval">
                <solid android:color="#1AFFFFFF"/>
            </shape>
            <color android:color="#FFF"/>
        </item>
    </ripple>
live-love
  • 48,840
  • 22
  • 240
  • 204
22

You can create circle ripple drawable using android:radius attribute in xml.

Example:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your_color"
    android:radius="your_radius" />

Pay attention, that your your_radius should be less then your view width and height. For example: if you have view with size 60dp x 60dp your_radius should be near 30dp (width / 2 or height / 2).

Work on Android 5.0 and above.

Volodymyr Yatsykiv
  • 3,181
  • 1
  • 24
  • 28
7

just add this item in your activity xml

           <ImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="?android:attr/actionBarItemBackground"
                app:srcCompat="@drawable/ic_arrow_drop_down_black_24dp" />
Ali Eslami
  • 83
  • 1
  • 6
7

update 2021:

you need use actionBarItemBackground for background

android:background="?android:attr/actionBarItemBackground"

Example:

 <androidx.appcompat.widget.AppCompatImageButton
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:background="?android:attr/actionBarItemBackground"
        android:src="@drawable/ic_copy" />
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78
3

If you want more generic XML files, I have two files:

1) btn_ripple_background with code:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:state_pressed="true"
    android:state_enabled="true"
    android:drawable="@drawable/ripple_circular_shape"/>
</selector>

2) ripple_circuler_shape with code:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/btn_state_pressed_text_color"
    android:shape="oval">
    <solid android:color="@color/btn_state_pressed_text_color" />
</shape>

finally the usage:android:foreground="@drawable/ripple_btn_background"

100RaBH
  • 161
  • 3
3

If you want ripple effect which will not cross the circle boundary, you can check this code. It works for me perfecrly. Just remember, you have to give id=@android:id/mask in ripple_blue.xml

<ImageButton
    android:id="@+id/send_password_to_mail_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_blue"
    android:src="@drawable/ic_filter" />

ripple_blue.xml

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorRipple">

    <item android:id="@android:id/mask">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

    <item android:id="@android:id/background">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

</ripple>

color.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <color name="colorWindowBackground">#F2F5FC</color>
    <color name="colorRipple">#0288d1</color>
</resources>
Aminul Haque Aome
  • 2,261
  • 21
  • 34
1

Try:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"
duduCMT
  • 41
  • 4
  • 2
    Please don't post only code as an answer, but include an explanation what your code does and how it solves the problem of the question. Answers with an explanation are generally of higher quality, and are more likely to attract upvotes. – Mark Rotteveel Nov 17 '19 at 10:13
  • Smoother than setting actionBarItemBackground as background. But still not exactly same as action bar animation itself. – coolcool1994 May 05 '20 at 01:16
1

I also fixed this problem in one of my projects. android:foreground="?attr/selectableItemBackgroundBorderless" is responsible for the ripple effect, that's why it is set in the foreground and android:clipToPadding="false" will prevent the ripple effect cut off and make it rectangular.It will keep your ripple effect circular.

<ImageButton
        android:id="@+id/navButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="8dp"
        android:foreground="?attr/selectableItemBackgroundBorderless"
        android:clipToPadding="false"
        android:src="@drawable/search_ic_back_arrow"/>
Gk Mohammad Emon
  • 6,084
  • 3
  • 42
  • 42
  • Not sure if you can put comments inside this way, and even then, you probably wanted to put each above. In addition, doesn't using `selectableItemBackgroundBorderless` mean it will be quite large for the case I've show (in a small area) ? Anyway, how do you change the color of the ripple this way? – android developer Jan 04 '21 at 15:57
0

In Kotlin / Java you can do the following

fun View.applyCircularRippleEffect() {
    val backgroundResId = context.getResource(android.R.attr.actionBarItemBackground)

    if (backgroundResId != 0) {
        setBackgroundResource(backgroundResId)
        isClickable = true
        isFocusable = true
    }
}

// getResource extension
fun Context.getResource(resourceId: Int): Int {
    val out = TypedValue()
    theme.resolveAttribute(resourceId, out, true)

    return out.resourceId
}
mihails.kuzmins
  • 1,140
  • 1
  • 11
  • 19