Ripple effect in Android

14 / Mar / 2016 by Apurv Pandey 3 comments

What is Ripple?

Ripple is a small wave like pattern, generally formed on the surface of some liquid when you drop something on it.

ripple

What is Ripple effect in Android?

Ripple effect provides an instantaneous visual confirmation at the point of contact when users interact with UI elements.

These UI elements could be any of the View elements.
Like – Layouts, Buttons, TextViews, ListViews, etc.

Whenever the user clicks or touches any UI element like, a button, it is desirable to provide some kind of visual confirmation, so that the user knows that their touch or click was successful. Responsive interaction encourages deeper exploration of an app by creating timely, logical, and delightful screen reactions to the user input. However, this interaction should not be distracting to the user. Traditionally in Android, this has been handled using state list drawables to provide different colored or shaded drawables which indicate that a control is in touched or pressed state. With the Android Lollipop, a new touch feedback mechanism was introduced to provide this touch feedback and is loosely based on the concept of ripples on the card metaphor which features strongly in Material design. These ripples are actually really easy to implement.

When was it introduced?

In the android development ecosystem, it was added in Android 5.0: API 21(LOLLIPOP). So, it does not work on pre-lollipop devices. However, we have external libraries which can be used to give the same effect. Links for the same are provided at the end of the blog.

Class hierarchy followed is :

[sourcecode language=”java”]
java.lang.Object
↳android.graphics.drawable.Drawable
↳android.graphics.drawable.LayerDrawable
↳android.graphics.drawable.RippleDrawable
[/sourcecode]

 

How to achieve Ripple effect?

It can be achieved in 2 ways :

(a) Programmatically – by using RippleDrawable class.
(b) By XML – by using Drawable XML that shows a ripple effect in response to state changes of         the View.

In order to understand how the ripple is drawn it would be nice to slow the animation down. The ripple animation runs slower when we perform a long press, so we can use that to see exactly what’s happening.

Programmatically

Our respective class will implement View.OnTouchListener interface.
It will provide us : public abstract boolean onTouch (View v, MotionEvent event) callback.
This is called, when a touch event is dispatched to a view.

Here, v : The view, the touch event has been dispatched to.
event : The MotionEvent object containing full information about the event.
This method returns True if the listener has consumed the event, False otherwise.

The anchoring position of the ripple for a given state is specified by calling setHotspot(float, float) with the corresponding state attribute identifier.

[sourcecode language=”java”]
private RippleDrawable rippleDrawable;
private Button buttonWithRipple;

buttonWithRipple = (Button) findViewById(R.id.buttonWithRipple);
rippleDrawable = (RippleDrawable) buttonWithRipple.getBackground();
buttonWithRipple.setOnTouchListener(this);

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.buttonWithRipple :
rippleDrawable.setHotspot(event.getX(), event.getY());
rippleDrawable.setColor(ColorStateList.valueOf(getResources().getColor(R.color.red)));
break; }
return false;
}
[/sourcecode]

Here, event.getX() & event.getY() gives us current pointer coordinates. And then, we set our required color to the rippledrawable object.

1

 

By XML

Setting DEFAULT Ripple effect on Android 5.0: API 21(LOLLIPOP) devices :

  • If you want to apply the Standard ripple effect on Android 5.0: API 21 or more, which should be limited to your view (bounded ripple), just apply to your View background :

[sourcecode language=”java”]        
android:background="?android:attr/selectableItemBackground"
[/sourcecode]

This background attribute value :

[sourcecode language=”java”]selectableItemBackground[/sourcecode]

will provide default ripple effect, which will constrain the animation, within the View that’s handling the touch event.

  • If you want to apply the standard ripple effect on Android 5.0: API 21 or more, which should not be limited to your view (unbounded ripple), just apply to your View background :

[sourcecode language=”java”]
android:background="?android:attr/selectableItemBackgroundBorderless"[/sourcecode]

This background attribute value :

[sourcecode language=”java”] selectableItemBackgroundBorderless[/sourcecode]

will provide default ripple effect, which will extend the animation beyond the bounds of its View that’s handling the touch event. It will be bounded by the nearest parent of the view with a non-null background.

2            3

Standard bounded Ripple Effect                 Standard Unbounded Ripple Effect

Setting CUSTOMISED Ripple effect on Android 5.0: API 21(LOLLIPOP) devices :

We create a touch feedback drawable that shows a ripple effect in response to state changes, using the ripple as root element.

This drawable may contain 0 or more child layers, including a special mask layer that is not drawn to the screen.

Attributes are as under :

  • android:color – the color to use for ripple effects.

1. Must be a color value, in the form of “#rgb”, “#argb”, “#rrggbb”, or “#aarrggbb”.
2. This may also be a reference to a resource (in the form “@[package:]type:name”) or theme           attribute (in the form “?[package:][type:]name”) containing a value of this type. This                       corresponds to the global attribute resource symbol color.

  • android:radius – radius of the ripple when fully expanded.

1. Default value is computed based on the size of the ripple’s container.
2. Must be a dimension value, which is a floating point number appended with a unit (like : px,          dp, sp, in, mm).
3. This may also be a reference to a resource (in the form “@[package:]type:name”) or theme        attribute (in the form “?[package:] [type:]name”) containing a value of this type. This                  corresponds to the global attribute resource symbol radius.

ripple1

USAGE :

Set this drawable as the background to your view :

[sourcecode language=”java”]android:background="@drawable/drawable_name"[/sourcecode]

  • Drawable with only a mask layer and no child layer
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/green"
        > 
        <item android:id="@android:id/mask"
            android:drawable="@color/green"
            >
        </item>
        
    </ripple>

If a mask layer is set and the ripple is set as a View background, the ripple effect will be masked against that layer.

 

  • Drawable with a child layer and a mask layer
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/green"
    >
    <item android:id="@android:id/mask"
        android:drawable="@color/green"
        >
    </item>
     <item
         android:drawable="@color/yellow">
     </item>
  
</ripple>

If a mask layer is set and the ripple is set as a View background, the ripple effect will be masked against that layer before it is drawn over the composite of the remaining child layers (if they exist).
Here, background color of button is changed by setting the child layer in the Ripple drawable XML.

 

  • Drawable with no mask layer or child layer
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/green"
    > 
</ripple>

If no child or mask layer is specified and the ripple is set as a View background, the ripple will be drawn atop the first available parent background within the View’s hierarchy.

 

4   5   croped_gif

Drawable with only a mask       Drawable with a mask     Drawable with no mask or

layer and no child layer             layer and a child layer      child layer

 

Below are the references to various libraries which can be used to apply Ripple Effect on Pre-Lollipop devices :

  • https://github.com/siriscac/RippleView.git
  • https://github.com/balysv/material-ripple.git
  • https://github.com/traex/RippleEffect.git
  • https://android-arsenal.com/tag/167

Thanks to Google for its Material Design   🙂

FOUND THIS USEFUL? SHARE IT

comments (3)

  1. neo

    Thank you for your article,it made me learn a lot, but i have just one question: when i set color attribute in ripper label,the drawable attribute in mask layer has no effect. can you explain why?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *