androidandroid-recyclerviewcardviewandroid-elevation

Android drag elevation translationz on cardview with itemTouchHelper in Recyclerview


i have a problem figuring out how to give cardViews temporarily elevation on drag. I use a recycler view with cardViews and this is my itemtouchhelper:

class ListTouchHelper extends ItemTouchHelper.Callback {

    private final ActionCompletionContract contract;

    public ListTouchHelper(ActionCompletionContract contract) {
        this.contract = contract;
    }
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        if (direction == ItemTouchHelper.LEFT) {
            contract.onViewSwipedLeft(viewHolder.getAdapterPosition());
        } else if (direction == ItemTouchHelper.RIGHT) {
            contract.onViewSwipedRight(viewHolder.getAdapterPosition());
        }
    }

    public interface ActionCompletionContract {
        void onViewMoved(int oldPosition, int newPosition);
        void onViewSwipedLeft(int position);
        void onViewSwipedRight(int position);
    }
}


I have managed to give it temporarily elevation with:
enter image description here

Which resulted in: (the shadows are somehow clipped?)
enter image description here

However, once the view is just slightly moved, the elevation disappears:
enter image description here

My question is: how do i get the elevation (including shadows) when the cards are being dragged?

Thanks in advance!


Solution

  • @LivinTheNoobLife in your solution you are using the ViewPropertyAnimator, but you are not setting any translation to it, hence, no animations will be applied.

    This is my solution with a properly working floating animation:

    class DragHelper extends ItemTouchHelper.Callback {    
    private boolean cardPicked = true;
    private boolean reset = false;
    
    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    
        // elevate only when picked for the first time
        if (cardPicked) { 
            ViewPropertyAnimator animator = viewHolder.itemView.animate();
            animator.translationZ(16);
            animator.setDuration(200);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.start();
    
            cardPicked = false;
        }
    
        // when your item is not floating anymore
        if (reset){
            ViewPropertyAnimator animator = viewHolder.itemView.animate();
    
            animator.translationZ(0);
            animator.setDuration(200);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.start();
    
            cardPicked = true;
            reset = false;
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
    
    // As the doc says
    // Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.
    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
    
         // interaction is over, time to reset our elevation
         reset = true;
    }
    }