版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014476720/article/details/84101229
效果图如下:
具体核心代码:
private ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//设置监听拖拽的方向
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();//得到item原来的position
int toPosition = target.getAdapterPosition();//得到目标position
if ((toPosition == listImgData.size() - 1 || listImgData.size() - 1 == fromPosition) && TextUtils.equals(listImgData.get(listImgData.size() - 1), "add")) {
return true;
}
//滑动事件
Collections.swap(listImgData, viewHolder.getAdapterPosition(), target.getAdapterPosition());
mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public boolean isLongPressDragEnabled() {
//是否可拖拽
return false;
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
viewHolder.itemView.setScaleX(1.1f);
viewHolder.itemView.setScaleY(1.1f);
}
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (!recyclerView.isComputingLayout()) {
//拖拽结束后恢复view的状态
viewHolder.itemView.setScaleX(1.0f);
viewHolder.itemView.setScaleY(1.0f);
}
}
});
这里是否可以拖拽都是靠 isLongPressDragEnabled 这个回调设置的,如果设置fase是不能拖拽的,由于我这里最后一个是不能进行拖拽的,但是设置false就全部不能进行拖拽了,我们的需要的效果就是其他可以拖拽,最后一个或者特定字符的不需要拖拽
先查看源码,发现这里使用了isLongPressDragEnabled
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
ItemTouchHelperGestureListener() {
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = findChildView(e);
if (child != null) {
ViewHolder vh = mRecyclerView.getChildViewHolder(child);
if (vh != null) {
if (!mCallback.hasDragFlag(mRecyclerView, vh)) {
return;
}
int pointerId = e.getPointerId(0);
// Long press is deferred.
// Check w/ active pointer id to avoid selecting after motion
// event is canceled.
if (pointerId == mActivePointerId) {
final int index = e.findPointerIndex(mActivePointerId);
final float x = e.getX(index);
final float y = e.getY(index);
mInitialTouchX = x;
mInitialTouchY = y;
mDx = mDy = 0f;
if (DEBUG) {
Log.d(TAG,
"onlong press: x:" + mInitialTouchX + ",y:" + mInitialTouchY);
}
if (mCallback.isLongPressDragEnabled()) {
select(vh, ACTION_STATE_DRAG);
}
}
}
}
}
}
上面源码ItemTouchHelperGestureListener是手指拖拽的一个监听
如果长按的时候isLongPressDragEnabled 返回false ,控件就不会出现拖拽
上面代码用于监听触摸手势
触摸手势的触摸监听又由下面代码传入触摸事件
最开始的触摸事件监听是RecyclerView的
由此可见,重新自定义一个触摸手势长按事件可满足我们的需求
想法:需要拖拽执行就必须执行 select(vh, ACTION_STATE_DRAG); 这个方法
看了看源码,尴尬,这个方法不能外部调用的,反正这个方法就是长按的时候可以让你拖拽
继续查看刚刚的按个是否可以长按拖拽,发现旁边有个 startDrag 的方法,
/**
* Returns whether ItemTouchHelper should start a drag and drop operation if an item is
* long pressed.
* <p>
* Default value returns true but you may want to disable this if you want to start
* dragging on a custom view touch using {@link #startDrag(ViewHolder)}.
*
* @return True if ItemTouchHelper should start dragging an item when it is long pressed,
* false otherwise. Default value is <code>true</code>.
* @see #startDrag(ViewHolder)
*/
public boolean isLongPressDragEnabled() {
return true;
}
发现startDrag 里面也是执行了 select(vh, ACTION_STATE_DRAG); 这个进行开始拖拽的
自定义手势触摸代码:
public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetectorCompat mGestureDetector;
private RecyclerView recyclerView;
public OnRecyclerItemClickListener(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener());
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
onItemClick(vh);
}
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
onItemLongClick(vh);
}
}
}
public abstract void onItemClick(RecyclerView.ViewHolder vh);
public abstract void onItemLongClick(RecyclerView.ViewHolder vh);
}
设置监听:
mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {
@Override
public void onItemClick(RecyclerView.ViewHolder vh) {
}
@Override
public void onItemLongClick(RecyclerView.ViewHolder vh) {
//如果item不是最后一个,则执行拖拽
if (vh.getLayoutPosition() != listImgData.size() - 1) {
helper.startDrag(vh);
} else if (!TextUtils.equals(listImgData.get(listImgData.size() - 1), "add")) {
helper.startDrag(vh);
}
}
});
上面就是大体代码了