Part 3b: RecyclerView from zero to hero.

Alfredo Cerezo Luna
3 min readFeb 27, 2018

Let’s make it shine: expanding circle background effect!

What you will find here:

During the last three posts: Part 1- First things first: implementing a basic RecyclerView , Part 2 — Giving it functionalities: swipe and drag & drop and Part 3-The devil is in the details: customise your items’ background, we learned how to implement a RecyclerView from zero, we learned how to add swipe gestures, and how to add a custom background to each element when it’s being swiped. Now, let’s make it shine! we are going to add an expanding circle animation to show us the progress of our gesture.

Swipe circle effect

Maybe you want to take a look to the previous articles to get some context, more precisely to the Part 3.

The idea:

The idea here is to paint a circle as a background instead of a rectangle, to do that, we are going to modify the class SwipeBackgroundHelper from the last post, now the method drawBackground():RectF should looks like this:

This code basically paints a circle of center cx and cy, these values are going to be calculated using the position of the item being swiped, and represented using a new Paint in our class:

private var circlePaint: Paint? = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.RED
}

Remember that coordinates in Android goes from up to button, and the coordinates of the item’s background are defined by a rectangle in absolute values.

The Y coordinate that specifies the center position of the circle will be the top position of the item’s background plus half of its height (this is the center of the rectangle that defines the background):

val cy = backgroundRectangle.top + viewItem.height / 2

and it’s X coordinate will be the left side position of the item’s background plus a fixed offset, this offset is going to add some separation between the center of the circle and the edge of the background that we are painting:

val cx = backgroundRectangle.left + leftOffset

to paint it’s radius we will do it according to the distance swiped

val circleRadius = (Math.abs(dX / viewItem.width) - threshold) * viewItem.width * CIRCLE_ACCELERATION

This value (Math.abs(dX / viewItem.width) will oscillate between 0 and 1 and viewItem.width * CIRCLE_ACCELERATION will represent the total length, we multiple it by CIRCLE_ACCELERATION to make the circle bigger, the size will differ but the time frame of the gesture will be the same, so that it will grow faster or slower depending on this value, play with it!

So far so good, but you might notice that we are painting too much stuff that it’s covered by other views, we just want to see a portion of the circle, so no need to paint it entirely, to fix that let’s going to “clip” the circle inside the rectangle that defines our background, we get this rectangle using the method getBackGroundRectangle()from the previous post, to clip means to ‘cut’ using the bounds provided and keeping what rests inside.

canvas.clipRect(backgroundRectangle)

And that’s it! Now just paint the circle:

canvas.drawCircle(cx, cy, circleRadius, circlePaint)

And you should have something like this:

Swipe circle effect

Summary

This post was very small, but very significant, we saw how just by adding a small animation we get a more responsive UI.
Specially thanks to Nick Butcher, he implemented this effect before me and shared his work, giving me the opportunity to adapt it to the needs of this example.

So this is the end, thank you for reading this, hopefully now you are a little bit better thanks to these posts, and that’s enough for me.

Happy coding!

Code:

https://github.com/Jachu5/recycler/blob/master/app/src/main/java/com/unchained/itemtouchexample/SwipeBackgroundHelper.kt

Reference:

Plaid Code: https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/ui/recyclerview/FilterTouchHelperCallback.kt

--

--