很多时候我们需要对列表进行一些操作,比如说股票的自选列表 我们希望能够拖拽删除置顶等操作。在recyclerveiw 之前 我们使用listview 完成这些操作 有点点麻烦,但是在recyclerview 出来之后ItemTouchHelper类使得一切变得简单。
先上图看下效果
/**
* Creates an ItemTouchHelper that will work with the given Callback.
* <p>
* You can attach ItemTouchHelper to a RecyclerView via
* {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration,
* an onItemTouchListener and a Child attach / detach listener to the RecyclerView.
*
* @param callback The Callback which controls the behavior of this touch helper.
*/
public ItemTouchHelper(Callback callback) {
mCallback = callback;
}
在我们创建 ItemTouchHelper 的时候 需要 传递一个Callback 对象。 官方的解释是 控制触摸事件的回调。也就是监听我们对列表的拖拽事件。我们看看callback 中具体我们要重写哪些回调
第一个就是 getMovementFlags 。
/**
* getMovementFlags 这个方法中我们可以设置拖拽和侧滑的方向 比如说我们现在是纵向列表 拖拽 设置
* makeMovementFlags(dragFlags, 0);第一个参数是拖拽的方向 ,我们设置的是ItemTouchHelper.UP | ItemTouchHelper.DOWN
* 上或者下、因为我们没有侧滑的需求所以swipeFlags 设置了0 如果我们的列表是网格列表 gridview
* 我们也可以根据 recyclerView.getLayoutManager() 来判断 然后
* 设置 ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT
*
* 如果是侧滑 我们需要把swipeFlags 设置成ItemTouchHelper.START | ItemTouchHelper.END
* @param recyclerView
* @param viewHolder
* @return
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN ;
return makeMovementFlags(dragFlags, 0);
}
第二个方法是 onMove 每次 拖动都会触发这个回调,每次回调我们可以在我们 adapter 中 操作我们的数据 每次拖动后我们把我们列表绑定书数组里 数据的位置也做下调整。
/**
* 顾名思义 当我们把一个 item 从一个位置拖到另一个位置 会触发这个回调
* @param recyclerView
* @param viewHolder ;老的 位置
* @param target 新的位置
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
interfaceTouchHelper.onItemMove(viewHolder, viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
public void onItemMove(RecyclerView.ViewHolder holder, int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(data, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(data, i, i - 1);
}
}
//刷新列表
notifyItemMoved(fromPosition, toPosition);
}
其他 需要重写的方法
/**
* 当选中的时候对 item进行 设置效果 放大 缩小 或者高亮
* @param viewHolder
* @param actionState
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
interfaceTouchHelper.onItemSelect(viewHolder);
}
super.onSelectedChanged(viewHolder,actionState);
}
/**
* 拖拽 结束后 我们 要对之前 做的 效果进行清除。 恢复正常状态
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (!recyclerView.isComputingLayout()) {
interfaceTouchHelper.onItemClear(viewHolder);
}
super.clearView(recyclerView,viewHolder);
}
/**
* 如果我们需要动态设置 能否拖动,则重写 isLongPressDragEnabled()方法 动态赋值,默认是true 的
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return isDrag;
}
我们写一个接口类 来处理选中 置顶 等 操作
public interface InterfaceOnCheckOrClickListener {
/**
* 点击拖动
*/
void onViewDragStart(MotionEvent event);
/**
* 停止拖动
*/
void onViewDragStop();
/**
* 置顶点击事件
* @param view
* @param position
*/
void onViewClick(View view, int position);
/**
* 选中的CheckBox
* @param view
* @param position
*/
void onCheckBoxSelected(View view, int position);
}
在我们的activity 中 继承这个接口 重写 onViewClick 方法
/**
* 点击置顶
* @param view
* @param position
*/
@Override
public void onViewClick(View view, int position) {
for (int i = position; i > 0; i--) {
Collections.swap(myAdapter.getData(), i, i - 1);
}
myAdapter.notifyDataSetChanged();
}
还有一些具体的代码实现不再赘述 直接上源码吧。