The thing is I'd like to perform an elevation on the item while it's being dragged in RecyclerView.
Based on what the documentation says, I am supposed to customize my dragged view's behaviors in ItemTouchHelper.Callback#onChildDraw because it says
If you would like to customize how your View's respond to user interactions, this is a good place to override.
Then I should clear my customizations in ItemTouchHelper.Callback#clearView because it says
Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.
But the problem is onChildDraw
will always be called one more time after clearView
.
So even if I cleared the customized behaviors in clearView
, still it will be re-called in onChildDraw
. Then what's the purpose of clearView
?
Here is my code:
class MyItemTouchCallback extends ItemTouchHelper.Callback {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP | ItemTouchHelper.DOWN);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
// Set elevation for dragged itemView
ViewCompat.setElevation(viewHolder.itemView, getResources().getDimension(R.dimen.common_elevation));
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
// Clear elevation for dragged itemView
ViewCompat.setElevation(viewHolder.itemView, 0);
}
}
Of course we can solve this problem with a trick, it's easy to understand. Remember with a boolean variable viewBeingCleared
when the dragged itemView is being cleared, then we can decide to call customized code in onChildDraw
or not.
However this is not the best solution. We'd better know why and then we will know how, isn't it?
Trick solution:
class MyItemTouchCallback extends ItemTouchHelper.Callback {
boolean viewBeingCleared;
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP | ItemTouchHelper.DOWN);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
if (viewBeingCleared) {
viewBeingCleared = false;
} else {
ViewCompat.setElevation(viewHolder.itemView, getResources().getDimension(R.dimen.common_elevation));
}
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
ViewCompat.setElevation(viewHolder.itemView, 0);
viewBeingCleared = true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With