5

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);
    }
}
Ryan Hoo
  • 360
  • 7
  • 19
  • 1
    When you release your finger, the `isCurrentlyActive` value becomes _false_. The `onChildDraw()` will still be called, but you don't need to set elevation anymore. Also, do not load your dimension resource in `onChildDraw()` every time - do it once in the constructor and save to a field. – Alex Semeniuk Jan 10 '19 at 11:22

2 Answers2

3

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;
    }
}
Ryan Hoo
  • 360
  • 7
  • 19
0

just check if (isCurrentlyActive)

ueen
  • 692
  • 3
  • 9
  • 21