Understanding swipe and drag gestures in RecyclerView

ishanknijhawan
Powerplay
Published in
5 min readOct 17, 2021

--

Ever wondered how these swipe gestures are implemented in Android? What if I told you that we can implement the exact same thing without any external library or complex code. In this article, we’ll not only make these Gmail like swipe gestures but also drag and drop actions like below

I’ll skimp on the basic parts like the item XML part and Adapter classes. You can check out the source code here for a full example at the end of this article. Here I’ll explain the logic of swipe and drag-drop actions.

Swipe gestures

First, let’s get the basic things done. We’ll need the device width and height, some icon references, color, and a basic list. We also made an extension function which we’ll use pretty extensively to convert all the pixel dimensions into dynamic pixels (dp).

Now that we have all the basic things set up, let’s dive into the interesting part. We had already declared our swipe helper at the top, time to fill some code in it.

We initialized our ItemTouchHelper with an object of the same. It takes 2 parameters viz. dragDirs and swipeDirs. For the former, we specified it as 0 because it’s better to keep the swipe logic and drag logic separate. As for the swipe directions, we want the item to be swipe-able from both sides. We can, and we will provide different functionalities for different directions. You can make the same depending upon your use case.

At this time the IDE gives an error and tells us to override 2 methods to be overridden. So we’ll respect our IDE and override these 2 methods. onMove() and onSwiped()

onMove() has no such significance in the swipe logic, in the onSwipe() is called after the item has been completely swiped by the user. You can make an API call, or delete a data entry or room, or show an alert dialog. Here I’m removing the item from a list and notifying the adapter. You can also check the direction in which the user has swiped by using the directions parameter as shown in the snackbar function.

Don’t forget to attach this helper with the RecyclerView like so

swipeHelper.attachToRecyclerView(rvList)

At this point, your swipe will work as expected but there’s something missing right? Ah, yes! Where’s the background you might ask, yeah we’re on it.

We’ll need to override the third method onChildDraw() , this method provides multiple parameters like canvas, the amount of swipe done in the horizontal and vertical direction, viewHolder instance, etc. We’ll need all those parameters to draw icons and colors while swiping in the left and right directions.

The above code might seem complex at first, but let’s walk through it step by step. In the first point, we’re setting the canvas’ background color based upon how much the user has swiped. Below is the graph for a better understanding of how we are changing color based upon dX value.

When dX < (deviceWidth / 3)or -dX < (-deviceWidth / 3). We show gray color. We can simply check the absolute value of dX should be less than (deviceWidth / 3).

Or if dX > (deviceWidth / 3) , show RED color. Else show GREEN.

The result of this code will be something like this.

We’re halfway done with our icon background implementation. Let’s put that icon in the place. For left to right swipe, we’ll display a Trash can icon and from right to left swipe, we’ll display an Archive icon. If you watch step 2 of the code snippet, I’ve set the bounds for both icons.

The Rect(…) object takes 4 parameters viz left, top, right, and bottom. These are the 4 points that we need to define in order to place the icon. The additional 16dp and 8dp in the vertical coordinates are due to the layout padding and drag icon padding, which is 16dp and 8dp respectively.

Remember, Rect(…) takes the coordinates and not the directional margins. For printing the icons, we are defining the coordinates from all 4 directions.

Lastly, we check if dX is positive, we draw the trash can icon, else the archive icon. And that’s it, you’ll the icons when swiping from either side of the view.

Drag and drop gesture

Drag and drop gesture is also done in a similar fashion as the swipe gesture. Except here, we specify the dragDirs as ItemTouchHelper.UP and ItemTouchHelper.DOWN , and swipeDirs as 0. If you are using a grid layout instead of a linear one, you can specify dragDirs in all directions. Below is the code for drag helper

Here we make use of the onMove() method and leave the onSwiped() empty. As we drag the item over other items, we swap the dragged item position with the target positions and notify the moved items.

You can also tweak the dragged item’s UI for a more ‘3D’ effect. I’ve increased the item’s elevation to 16 units while it moves, and then set it to 0 units in onSelectedChange() callback.

And just like the swipeHelper, you need to attach this helper to the RecyclerView

dragHelper.attachToRecyclerView(rvList)

This approach will require the user to long-press the item in order to activate the drag functionality, which is okay in most cases. But what if you want a drag-handle, which you don’t have to long press and is always active from dragging? Thankfully, it’s really simple with the help of a built-in function.

And now you have to call this function from your adapter’s onBindViewHolder() method like so.

Make sure to pass context as MainActivity.kt in the Adapter so as to be able to call the function

And that’s it! Your drag handle is always active from dragging your item as shown in the initial GIF. Fire up some comments or suggestions in case I missed something.

You can refer to the source code below. Any doubts are most welcome in the comment section.

Cheers 🍹

--

--