Inbox Style Swipe ListView
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 ListView
and ArrayAdapter
.
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.
Design Layout
As I said, we would create three different layers and add them to a RelativeLayout.
ArrayAdapter
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.
Swipe Detector
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.
When 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 MIN_LOCK_DISTANCE
?
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.
Final Steps
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.
Playing around with Android UI
Articles focusing on Android UI - playing around with ViewPagers, CoordinatorLayout, meaningful motions and animations, implementing difficult customized views, etc.