EDIT: The real problem was that my LinearLayout
was wrapped in another layout, which caused the incorrect behavior. The accepted answer by Sanvywell has a better, more complete example of how to draw a color under swiped view than the code snippet I provided in the question.
Now that RecyclerView widget has native support for row swiping with the help of ItemTouchHelper class, I'm attempting to use it in an app where rows will behave similarly to Google's Inbox app. That is, swiping to the left side performs one action and swiping to the right does another.
Implementing the actions themselves was easy using ItemTouchHelper.SimpleCallback's onSwiped
method. However, I was unable to find a simple way to set color and icon that should appear under the view that's currently being swiped (like in Google's Inbox app).
To do that, I'm trying to override ItemTouchHelper.SimpleCallback's onChildDraw
method like this:
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
RecyclerViewAdapter.ViewHolder vh = (RecyclerViewAdapter.ViewHolder) viewHolder;
LinearLayout ll = vh.linearLayout;
Paint p = new Paint();
if(dX > 0) {
p.setARGB(255, 255, 0, 0);
} else {
p.setARGB(255, 0, 255, 0);
}
c.drawRect(ll.getLeft(), ll.getTop(), ll.getRight(), ll.getBottom(), p);
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
Determining the swipe direction from dX and setting the appropriate color works as intended, but the coordinates I get from the ViewHolder
always correspond to the place where the first LinearLayout
was inflated.
How do I get the correct coordinates for the LinearLayout
that's in the currently swiped row? Is there an easier way (that doesn't require to override onChildDraw
) to set the background color and icon?
The accepted answer does a great job of coloring the background, but did not address drawing the icon.
This worked for me because it both set the background color and drew the icon, without the icon being stretched during the swipe, or leaving a gap between the previous and next items after the swipe.
HappyKatz solution has a tricky bug. Is there any reason for drawing bitmap when dX==0?? In some cases this causes permanent icon visibility above list item. Also icons become visible above list item when you just touch list item and dX==1. To fix these:
I was struggling to implement this feature as well, but you steered me in the right direction.
I'm not sure how these solutions (by @Sanvywell, @HappyKatz and @user2410066) are working for you guys but in my case I needed another check in the
onChildDraw
method.Looks like
ItemTouchHelper
keepsViewHolder
s of removed rows in case they need to be restored. It's also callingonChildDraw
for those VHs in addition to the VH being swiped. Not sure about memory management implications of this behavior but I needed an additional check in the start ofonChildDraw
to avoid drawing for "fantom" rows.BONUS PART:
I've also wanted to continue drawing as other rows animate to their new positions after a row is swipe deleted, and I couldn't do it within
ItemTouchHelper
andonChildDraw
. In the end I had to add another item decorator to do it. It goes along these lines:UPDATE: I wrote a blog post on recycler view swipe to delete feature. Someone might find it usefull. No 3rd party lib necessary.
blog post git repo
In order to implement I used the sample code created by Marcin Kitowicz here.
Benefits of this solution:
The original implementation code can be found here. In order to implement left swipe I used the inverse left and right positioning logic.