package com.netease.nim.uikit.common.ui.recyclerview.callback; import android.graphics.Canvas; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; import com.netease.nim.uikit.R; import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseItemDraggableAdapter; public class ItemDragAndSwipeCallback extends ItemTouchHelper.Callback { // private static final String TAG = ItemDragAndSwipeCallback.class.getSimpleName(); BaseItemDraggableAdapter mAdapter; float mMoveThreshold = 0.1f; float mSwipeThreshold = 0.7f; int mDragMoveFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; int mSwipeMoveFlags = ItemTouchHelper.END; public ItemDragAndSwipeCallback(BaseItemDraggableAdapter adapter) { mAdapter = adapter; } @Override public boolean isLongPressDragEnabled() { return false; } @Override public boolean isItemViewSwipeEnabled() { return mAdapter.isItemSwipeEnable(); } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { if (actionState == ItemTouchHelper.ACTION_STATE_DRAG && !isViewCreateByAdapter(viewHolder)) { mAdapter.onItemDragStart(viewHolder); viewHolder.itemView.setTag(R.id.BaseQuickAdapter_dragging_support, true); } else if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && !isViewCreateByAdapter(viewHolder)) { mAdapter.onItemSwipeStart(viewHolder); viewHolder.itemView.setTag(R.id.BaseQuickAdapter_swiping_support, true); } super.onSelectedChanged(viewHolder, actionState); } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); if (isViewCreateByAdapter(viewHolder)) { return; } if (viewHolder.itemView.getTag(R.id.BaseQuickAdapter_dragging_support) != null && (Boolean) viewHolder.itemView.getTag(R.id.BaseQuickAdapter_dragging_support)) { mAdapter.onItemDragEnd(viewHolder); viewHolder.itemView.setTag(R.id.BaseQuickAdapter_dragging_support, false); } if (viewHolder.itemView.getTag(R.id.BaseQuickAdapter_swiping_support) != null && (Boolean) viewHolder.itemView.getTag(R.id.BaseQuickAdapter_swiping_support)) { mAdapter.onItemSwipeClear(viewHolder); viewHolder.itemView.setTag(R.id.BaseQuickAdapter_swiping_support, false); } } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { if (isViewCreateByAdapter(viewHolder)) { return makeMovementFlags(0, 0); } return makeMovementFlags(mDragMoveFlags, mSwipeMoveFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { if (source.getItemViewType() != target.getItemViewType()) { return false; } else { return true; } } @Override public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder source, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) { mAdapter.onItemDragMoving(source, target); } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { if (!isViewCreateByAdapter(viewHolder)) { mAdapter.onItemSwiped(viewHolder); } } @Override public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) { return mMoveThreshold; } @Override public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) { return mSwipeThreshold; } /** * Set the fraction that the user should move the View to be considered as swiped. * The fraction is calculated with respect to RecyclerView's bounds. * <p> * Default value is .5f, which means, to swipe a View, user must move the View at least * half of RecyclerView's width or height, depending on the swipe direction. * * @param swipeThreshold A float value that denotes the fraction of the View size. Default value * is .8f . */ public void setSwipeThreshold(float swipeThreshold) { mSwipeThreshold = swipeThreshold; } /** * Set the fraction that the user should move the View to be considered as it is * dragged. After a view is moved this amount, ItemTouchHelper starts checking for Views * below it for a possible drop. * * @param moveThreshold A float value that denotes the fraction of the View size. Default value is * .1f . */ public void setMoveThreshold(float moveThreshold) { mMoveThreshold = moveThreshold; } /** * <p>Set the drag movement direction.</p> * <p>The value should be ItemTouchHelper.UP, ItemTouchHelper.DOWN, ItemTouchHelper.LEFT, ItemTouchHelper.RIGHT or their combination.</p> * You can combine them like ItemTouchHelper.UP | ItemTouchHelper.DOWN, it means that the item could only move up and down when dragged. * * @param dragMoveFlags the drag movement direction. Default value is ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT. */ public void setDragMoveFlags(int dragMoveFlags) { mDragMoveFlags = dragMoveFlags; } /** * <p>Set the swipe movement direction.</p> * <p>The value should be ItemTouchHelper.START, ItemTouchHelper.END or their combination.</p> * You can combine them like ItemTouchHelper.START | ItemTouchHelper.END, it means that the item could swipe to both left or right. * * @param swipeMoveFlags the swipe movement direction. Default value is ItemTouchHelper.END. */ public void setSwipeMoveFlags(int swipeMoveFlags) { mSwipeMoveFlags = swipeMoveFlags; } @Override public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && !isViewCreateByAdapter(viewHolder)) { View itemView = viewHolder.itemView; c.save(); if (dX > 0) { c.clipRect(itemView.getLeft(), itemView.getTop(), itemView.getLeft() + dX, itemView.getBottom()); c.translate(itemView.getLeft(), itemView.getTop()); } else { c.clipRect(itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); c.translate(itemView.getRight() + dX, itemView.getTop()); } mAdapter.onItemSwiping(c, viewHolder, dX, dY, isCurrentlyActive); c.restore(); } } private boolean isViewCreateByAdapter(RecyclerView.ViewHolder viewHolder) { int type = viewHolder.getItemViewType(); if (type == mAdapter.HEADER_VIEW || type == mAdapter.LOADING_VIEW || type == mAdapter.FOOTER_VIEW || type == mAdapter.EMPTY_VIEW) { return true; } return false; } }