Add ripple effect to my button with button background color?
Asked Answered
C

13

168

I created a button and I want to add ripple effect to that button!

I created a button bg XML file: (bg_btn.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFFFF" android:endColor="#00FF00" android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>

And this is my ripple effect file: (ripple_bg.xml)

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

And This is my Button which I want to add ripple effect:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="173dp"
android:textColor="#fff"
android:background="@drawable/ripple_bg"
android:clickable="true" />

But after adding ripple effect button background is transparent, and button display only when clicked, like this:

Before Click

On Click

But I need both button background color and ripple effect, I found some of this code in different blogs of Stack Overflow, but still it is not working!

Cribble answered 12/10, 2016 at 21:25 Comment(3)
please make screenshots much smaller next time.. (resize before uploading)Extracellular
@user25, you can also just add an l or m to the image link. (see my edit)Filiation
Those who wanted to relay on foreground property, use this hack for backward compatibility - https://mcmap.net/q/27114/-add-ripple-effect-to-my-button-with-button-background-colorClough
P
248

Here is another drawable xml for those who want to add all together gradient background, corner radius and ripple effect:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimaryDark">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryLight"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>
</ripple>

Add this to the background of your button.

<Button
    ...
    android:background="@drawable/button_background" />

PS: this answer works for android api 21 and above.

Pageboy answered 24/9, 2017 at 17:38 Comment(10)
@pei How you guys get this infos from? I mean how you know that there's an XML element called ripple to do this job?Lilias
It's one of the concepts used in material design. Please start typing a new root tag in a drawable xml in Android Studio then you should be able to see all the available tags including ripple.Pageboy
what is the use of mask item?Inesita
It's the mask in which ripple effect is applied. Without it you won't be able to make the ripple effect to be in the same shape of the background.Pageboy
this requires api level 21Cavalcade
it works but how it works is not explained. it should be related with item's id. Should be referenced.Register
@Pei, where do you place this file? in the anim folder?Assuage
@Assuage As you can see in the statement android:background="@drawable/button_background", you should place this in the drawable folder.Northeastwards
For those who are using a custom background for their View, you can set android:foreground="?attr/selectableItemBackground".Lavine
Sorry but the gradient part just doesn't work for me. The button has just colorprimary as background, no gradient. I checked that colorprimarydark is different from colorprimary so that's not the issue.Incompressible
B
213

Add the "?attr/selectableItemBackground" to your view's android:foreground attribute if it already has a background along with android:clickable="true".

Bradybradycardia answered 22/6, 2017 at 10:6 Comment(6)
doesn't always work, but you can add a background to the ripple effect as noted in the comments of the accepted answerShoemaker
I had to use this solution as I have used a custom background for my button. It worked great.Appose
@ROAR, that's right, but at least: "This is not an error; the application will simply ignore the attribute. However, if the attribute is important to the appearance or functionality of your application, you should consider finding an alternative way to achieve the same result with only available attributes, and then you can optionally create a copy of the layout in a layout-vNN folder which will be used on API NN or higher where you can take advantage of the newer attribute." So it works well on devices above API 23 and is ignored when below (we can just tools:ignore="UnusedAttribute).Rothko
without Android support library, it would be ?android:attr/selectableItemBackground (android:attr instead of attr)Fishwife
android:foreground attribute has not effect on API levels lower than 23Defenestration
@VadimKotov Google should completely ban all API levels smaller than 23. I find absolutely 0 excuse for companies to still request development for such prehistoric versions.Caravaggio
M
81

Add Ripple Effect/Animation to a Android Button

Just replace your button background attribute with android:background="?attr/selectableItemBackground" and your code looks like this.

      <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="New Button" />

Another Way to Add Ripple Effect/Animation to an Android Button

Using this method, you can customize ripple effect color. First, you have to create a xml file in your drawable resource directory. Create a ripple_effect.xml file and add following code. res/drawable/ripple_effect.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="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

And set background of button to above drawable resource file

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />
Meltage answered 12/10, 2016 at 21:37 Comment(3)
For me, ripple effect did not appear. it was just a color switch for the button :/ My android version is 5.1.1 so it should work. Could you help? I followed your stepsJeth
android:color should be different from the mast android:color, or you want see the ripple effectFantasm
if you want a background you just add another item to the ripple, like: <item android:drawable="?attr/colorPrimary"/>Shoemaker
V
45

In addition to Jigar Patel's solution, add this to the ripple.xml to avoid transparent background of buttons.

<item
    android:id="@android:id/background"
    android:drawable="@color/your-color" />

Complete xml :

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/your-color"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/your-color" />
        </shape>
    </item>
    <item
        android:id="@android:id/background"
        android:drawable="@color/your-color" />
</ripple>

Use this ripple.xml as background in your button :

android:background="@drawable/ripple"
Vice answered 31/5, 2017 at 7:29 Comment(7)
We didn't need to use the <item android:id="@android:id/mask"> [...]. Unless you want an oval mask. Thanks for your answer!Zelmazelten
What does this <item android:id="@android:id/mask"> do anyway, I created 2 similar elements with and without that attribute, and they look exactly the sameNelia
@SartherisStormhammer from official docs: If a mask layer is set, the ripple effect will be masked against that layer before it is drawn over the composite of the remaining child layers. If no mask layer is set, the ripple effect is masked against the composite of the child layers. This is the link, developer.android.com/reference/android/graphics/drawable/…Vice
@SudheeshR that just makes it more confusingNelia
@SartherisStormhammer From that official documentation It's pretty clear I think. Ripple effect will draw over child/masked layers. Please read the doc again, you'll get the point.Vice
You need to use different colors for ripple and for background, but not the same "@color/your-color"Dickey
Absolutely. I didn't meant those are same colors.. Just use whatever color you want..Vice
Q
40

When the button has a background from the drawable, we can add ripple effect to the foreground parameter.. Check below code its working for my button with a different background

    <Button
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"                                                             
    android:background="@drawable/shape_login_button"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:text="@string/action_button_login"
     />

Add below parameter for the ripple effect

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

For reference refer below link https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/

Qualls answered 7/9, 2017 at 11:25 Comment(2)
Attribute android:foreground has no effect on API levels lower than 23Manzanilla
One drawback of this approach is, even though my button background was oval the ripple propagated till the rectangular edges.Substantiate
B
26

AppCompat v7+

If you don't prefix with ?android: your app will crash.

You should use "?android:attr/selectableItemBackground" or "?android:attr/selectableItemBackgroundBorderless", based on your preference. I prefer Borderless.

You can put it either in android:background or android:foreground to keep existing properties.

The element must have android:clickable="true" and android:focusable="true" in order for this to work, but many elements, such as buttons, have them true by default.

<Button
    ...
    android:background="@color/white"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
/>
<TextView
    ...
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:focusable="true"
/>

Programmatically (Java)

TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
myView.setBackgroundResource(value.resourceId);
myView.setFocusable(true); // If needed for view type

Programmatically (Kotlin)

val value = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
myView.setBackgroundResource(value.resourceId)
myView.setFocusable(true) // If needed for view type

Reusable Kotlin Extension Function

myView.ripple()

fun View.ripple(): View {
    val value = TypedValue()
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
    setBackgroundResource(value.resourceId)
    isFocusable = true // Required for some view types
    return this
}
Because answered 28/4, 2018 at 23:25 Comment(2)
If you add ?android you won't be using the AppCompat lib, but the one from the OS (so it will crash in api<11). You have to use it without the android: namespace prefix.Cohort
Thanks for the note 📝. I'd expect most devs have min level above 11, so no problemBecause
S
8

Adding foreground and clickable attributes worked for me.

<Button
    ... 
    android:background="@color/your_color"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true" />
Superstratum answered 26/3, 2018 at 15:27 Comment(1)
Api level 23 abovePteropod
C
8

A simple approach is to set a view theme as outlined here.

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>
Cloyd answered 27/3, 2020 at 20:42 Comment(0)
A
7

In addition to Sudheesh R

Add Ripple Effect/Animation to a Android Button with button rectangle shape with corner

Create xml file res/drawable/your_file_name.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/colorWhite"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="50dp" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorAccent"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="50dp" />
        </shape>
    </item>
</ripple>
Albania answered 7/11, 2017 at 8:57 Comment(0)
V
5

Try this:

<Button
    android:background="@drawable/btn_corner"
    android:clickable="true"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:gravity="center_vertical|center_horizontal"
    android:id="@+id/btn_location"
    android:layout_gravity="center"
    android:layout_height="38dp"
    android:layout_marginBottom="24dp"
    android:layout_marginTop="24dp"
    android:layout_width="121dp"
    android:paddingLeft="13dp"
    android:paddingRight="13dp"
    android:text="Save"
    android:textColor="@color/color_white" />
Vigesimal answered 23/12, 2017 at 5:27 Comment(0)
S
3

Just use :

android:backgroundTint="#f816a463"

Instead of:

android:background="#f816a463"

Don't forget to change your Button to android.support.v7.widget.AppCompatButton

Seisin answered 29/6, 2017 at 15:44 Comment(1)
The bad is that if you need a button to fill 100% the horizontal screen you won't.Zelmazelten
S
2

An alternative solution to using the <ripple> tag (which I personally prefer not to do, because the colors are not "default"), is the following:

Create a drawable for the button background, and include <item android:drawable="?attr/selectableItemBackground"> in the <layer-list>

Then (and I think this is the important part) programmatically set backgroundResource(R.drawable.custom_button) on your button instance.

Activity/Fragment

Button btn_temp = view.findViewById(R.id.btn_temp);
btn_temp.setBackgroundResource(R.drawable.custom_button);

Layout

<Button
    android:id="@+id/btn_temp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/custom_button"
    android:text="Test" />

custom_button.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item android:drawable="?attr/selectableItemBackground" />
</layer-list>
Seller answered 4/2, 2019 at 10:54 Comment(1)
Why should programmaticallly set backgroundResource again, while layout xml defines Button's background?Arrowworm
C
1

setForeground is added in API level 23. Leverage the power of RevealAnimator in case u need to relay on foreground property !

 <View
   android:id="@+id/circular_reveal"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="@color/primaryMilk_22"
   android:elevation="@dimen/margin_20"
   android:visibility="invisible" />

With kotlin ext function, it's way osm !

fun View.circularReveal() {
    val cx: Int = width / 2
    val cy: Int = height / 2
    val finalRadius: Int =
        width.coerceAtLeast(height)
    val anim: Animator = ViewAnimationUtils.createCircularReveal(
        this,
        cx,
        cy,
        0f,
        finalRadius.toFloat()
    )
    anim.interpolator = AccelerateDecelerateInterpolator()
    anim.duration = 400
    isVisible = true
    anim.start()
    anim.doOnEnd {
        isVisible = false
    }
}
Clough answered 9/12, 2020 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.