Google’s Inbox application has a really nice ListView where user could swipe right to mark the email done and swipe left to snooze the notification. I implemented something very similar to that using
The method that I used here is quite simple. I created a RelativeLayout which would be used to display each item of the listview. This RelativeLayout has three different layouts. Top layout is the one that you would want to show. Each layers are stacked. The second layer shows delete option. Third layer shows share option.
When the user swipes right, the second layer starts showing from the left. But when the user swipes left, it should show the third layer, so we need to make second layer invisible. That’s about it. Just a simple trick.
As I said, we would create three different layers and add them to a RelativeLayout.
Now, we need to create a class which extends ArrayAdapter. Here, we will create a holder for each entry. We will also create a swipe detector which would be helpful in swiping the list items.
Dectcting swipe movement is an important part here. We create a class which extends
View.onTouchListener and attach it to the top most view of the layout. Now, all we need to do is animate the view as the user swipes it. It is not that difficult. As I have shown previously, that you can do this by changing left and right margin of the view by the same amount.
When it receives
ACTION_DOWN event, we will store the x co-ordinate of the touch. And after which whenever it will receive
ACTION_MOVE event, we will store the new x co-ordinate and calculate the difference between current co-ordinate and the initial touch co-ordinate. Based on this difference, we will change the margins of the top view, and hide second view (if swipe is in left direction).
One might wonder why I have added something like
requestDisallowInterceptTouchEvent in this code. I had not added it before. It was just simple code - swipe and be done with it. But I faced a problem. There was no issue if I swiped it properly, but if my finger accidentally swiped the item in vertical direction, the ListView would intercept that touch event and take control of it. So
onTouchListener would give
ACTION_CANCEL as the event. Here is a good stackoverflow answer which explains why this happens.
reqeustDisallowInterceptTouchEvent(true) is called on the ListView, it doesn’t intercept the vertical swipe gesture and the horizontal swipe works well.
Why have I used
If I don’t use that and just disallow intercepting the events, even ACTION_DOWN would disallow intercepting the event and hence disabling the vertical scrolling. You would never be able to scroll your list. Hence, if you keep a threshold of say, 20, then if you have swiped the list horizontally by a distance 20px, listview will stop intercepting the events and you’d get proper swipe interaction.
One last step would be to set up the ListView and Adapter.
And the final result looks something like this.
P.S. Working on UI is fun, but sometimes becomes a headache.
EventBus is a design pattern which allows publish-subscribe style communication without requiring components to registering with each other. In this article, I explore EventBus and demonstrate how it can be used to communicate between activities and services in Android.