RecyclerView之使用ItemTouchHelper和ItemTouchHelper.Callback实现条目拖拽排序

我们先来看看效果图:

RecyclerView之使用ItemTouchHelper和ItemTouchHelper.Callback实现条目拖拽排序_第1张图片

这里简单的RecyclerView列表就不说了,我们直接来重点,实现这个效果我们分两步:

一.实现条目拖拽 :鼠标点击条目的某一个控件(这里我选择的是条目中的image)不松开移动鼠标,条目跟着动.

1.如何开启条目拖动呢?很简单,调用

 ItemTouchHelper.startDrag(ViewHolder viewHolder);
2.在什么条件下开启条目拖动呢?
a.鼠标要点击image不松开 
((MyViewHoder)viewHolder).imageView.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction()==MotionEvent.ACTION_DOWN) {
					// 传递触摸情况给ItemTouchHelper  调用 ItemTouchHelper.startDrags()方法
					if (mStartDragListener!=null) {
						mStartDragListener.onStartDrag(viewHolder);
					}
				}
				return false;
			}
		});
b. 不松开之后做上下移动的动作时需要ItemTouchHelper开启回调
 public class MyItemTouchCallBack extends Callback {

	@Override
	public int getMovementFlags(RecyclerView recyclerView,ViewHolder viewHolder) {
		// TODO Auto-generated method stub
		// Flags  是十六进制的运算结果
		// CallBack回调监听时先调用的  用来判断当前是什么动作比如判断方向(意思是我要监听哪个方向的拖动)
		// 方向: up 、down 、 left 、right
		// 多个方向时 返回的还是一个值  所以这里存在   与运算(&)和 或运算(|)       0:表示"非"  1:表示"是"
		int up = ItemTouchHelper.UP;//      1:0x0001
		int down = ItemTouchHelper.DOWN;//  2:0x0010		
		int dragFlags = up | down;
		/**
		 * drags :  拖拽(up/down)
		 * swipe :  侧滑(lef/fight)
		 * makeMovementFlags(dragFlags, swipeFlags);
		 * **/
		return makeMovementFlags(dragFlags, 0);
	}
 }
3.在哪里调用ItemTouchHelper.startDrag(ViewHolder viewHolder);最合适?
  看参数我们就知道要在adapter中调用方便,但是将ItemTouchHelper传入Adapter中太low了 
  所以两个类的连接我们用interface 连接所以我们创建一个接口(作用就是当我们短按摸个条目的image是将此时的ViewHolder传递到拥有ItemTouchHelper的activity调用startDrag方法):
 public interface StartDragListener {
	/**
	 * 该接口用于主动回调拖拽效果
	 * @param viewHolder
	 */
	public void  onStartDrag(ViewHolder viewHolder);
 }
 在拥有ItemTouchHelper的Activity中实现回调,调用ItemTouchHelper.startDrag(ViewHolder viewHolder);开启拖拽

@Override
public void onStartDrag(ViewHolder viewHolder){
    	//开启条目拖动
    	itemTouchHelper.startDrag(viewHolder);	
}

二.实现排序(就是讲条目拖拽到某个位置松开后嵌入该位置)

 首先我们知道我们的RecyclerView的:

Adapter.notifyItemMoved(int fromPosition,int  toPosition);
可以实现,所以我们要在条目移动的时候调用该方法,所以我们现在依然要创建一个借口用于连接ItemTouchHelper.Callback和Adapter:

public interface ItemTouchMoveListener {

	/**
	 * 当拖拽的时候回调此方法
* 在此方法中可以实现:拖拽条目并实现刷新效果 * @param fromPosition 从什么位置 * @param toPosition 到什么位置 * @return 是否回调 */ public boolean onItemMove(int fromPosition,int toPosition); }
在Adapter中实现:

	@Override
	public boolean onItemMove(int fromPosition, int toPosition) {
		// 1. 数据交换  2. 刷新RecyclerView
		Collections.swap(mDatas, fromPosition, toPosition);
		notifyItemMoved(fromPosition, toPosition);
		return true;
	}

在ItemTouchHelper.Callback.的move方法中调用:

@Override
public boolean onMove(RecyclerView recyclerView,ViewHolder viewHolder, ViewHolder target) {
	// TODO Auto-generated method stub
	// 当移动的时候回调的方法
	if (viewHolder.getItemViewType()!=target.getItemViewType()) {
		//不同的条目不进行交换
		return false;
	}
	mItemTouchMoveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
	return true;
}





你可能感兴趣的:(RecyclerView)