Drawables / Ripple Drawable

Ripples – Part 2

In the previous article we began looking an RippleDrawable which was introduced in the Android-L developer preview. In this article we’ll look at ways in which we can control the look of our Ripple.

In the previous article we saw how the actual Ripple animation extends beyond the bounds of its parent control, and while this is useful to be able to see how the animation actually works, it does not show the desired effect for the end user. So let’s look at how we can constrain the animation within the View that’s handling the touch event.

The first way of doing this is to define a mask on the drawable:

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

The use of the id @android:id/mask declares this as being a mask, and the mask defines the bounds for the ripple animation. I have included a solid fill within the shape drawable which defines the mask area. This can be omitted without changing anything – I have included it (set to a bright green from the colorAccent attribute) so that it is clear that the mask is not actually rendered, it just defines the bounds of the ripple:

Another way that we can confine the bounds of a ripple animation is to actually define a shape drawable as a child and omit the @android:id/mask id:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  android:color="?android:colorControlHighlight">
  <item>
    <shape android:shape="rectangle">
      <stroke
        android:color="?android:colorAccent"
        android:width="1dp" />
    </shape>
  </item>
</ripple>

This has precisely the same effect on the bounds of the ripple animation as the mask, but the big difference here is that this shape will be drawn as well. So by including a stroke of the accent colour we are effectively creating a visual frame which will also constrain the ripple animation:

The fact than we can include the frame within the ripple drawable itself is really nice because we are defining the ripple as the background to its View, and this is where we would normally use a frame drawable.

Now for a little nasty. Suppose we took the last example and changed the shape to an oval:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  android:color="?android:colorControlHighlight">
  <item>
    <shape android:shape="oval">
      <stroke
        android:color="?android:colorAccent"
        android:width="1dp" />
    </shape>
  </item>
</ripple>

We would expect this to work exactly the same as a rectangle, only with an oval frame and the ripple animation bounded by the oval. However if we try this, we see no ripple animation at all:

There seems to be a discrepancy between how an oval and a rectangle are handled, but there is an easy way to get this working by adding an oval mask as well as the oval frame:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  android:color="?android:colorControlHighlight">
  <item android:id="@android:id/mask">
    <shape android:shape="oval">
      <solid android:color="?android:colorAccent" />
    </shape>
  </item>
  <item>
    <shape android:shape="oval">
      <stroke
        android:color="?android:colorAccent"
        android:width="1dp" />
    </shape>
  </item>
</ripple>

If we now try this we see exactly the behaviour that we want:

It is worth remembering that the Android-L developer preview is a pre-release and has a few rough edges which could explain this minor inconsistency. However, it’s no great hardship to define both the mask and frame separately in order to get things working.

In the concluding article in this series we’ll take a look at how we can change the colours used in the ripple animation.

The source code for this article is available here.

© 2014, Mark Allison. All rights reserved.

Copyright © 2014 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.

1 Comment

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.