概述
列表数据显示越来越多的使用RecyclerView来实现,借助ItemTouchHelper实现长按拖动,滑动删除也更加方便
简单实现
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(mView.rvDesktopAppsort);
简单实现只能达到效果,但实际的数据处理并未发生变化,需要自定义Callback来实现,简单实现也要new一个Callback出来
自定义Callback
定义一个接口来回调Adapter中绑定的具体事件
public interface ITouchHelperAdapter {
//Item长按拖动事件
void onItemMove(int fromPosition, int toPosition);
//滑动删除后清理事件
void onItemSwip(int position);
//是否允许滑动删除
boolean canSwip();
}
自定义 SimpleTouchHelperCallback
重点重写几个方法
- getMovementFlags # 设置滑动和拖动的方向
- onMove # 长按拖动事件
- onSwiped # 滑动删除事件
如果需要控制是否允许滑动删除,还要重写一个方法
- isItemViewSwipeEnabled # 通过返回true或false来控制是否允许滑动删除
在Callback中构造函数中传入继承了上面接口的Adapter以取得具体回调事件
public class SimpleTouchHelperCallback extends ItemTouchHelper.Callback {
private final ITouchHelperAdapter adapter;
public SimpleTouchHelperCallback(ITouchHelperAdapter adapter) {
this.adapter = adapter;
}
//定义长按拖动和滑动的方向,返回0表示禁止滑动
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
//滑动方向,此处只开启右滑删除(END代表阅读习惯结束的方向)
int swipFlag = ItemTouchHelper.END;
//长按拖动方向,上下左右都可拖动
int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlag, swipFlag);
}
//长按拖动事件,回调接口中的 onItemMove() 方法
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
//侧滑删除后的清理事件
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemSwip(viewHolder.getAdapterPosition());
}
//是否开启侧滑删除功能,在外部通过返回布尔值来达到控制
@Override
public boolean isItemViewSwipeEnabled() {
return adapter.canSwip();
}
//是否开启长按拖动功能,返回true表示开启
@Override
public boolean isLongPressDragEnabled() {
return true;
}
}
PS
目前无法在侧滑移除之前进行拦截,只能通过是否允许侧滑来控制是否删除。因为一旦调用了侧滑事件,UI上即已经移除了Item,如果不处理相应的Adapter移除动作,则会造成不同步。手动呼叫侧滑又没有相应的触发事件。
有解决方案的朋友望指教一二,先谢谢了。
Adapter中继承接口并实现具体方法内容
public class ReferItemAdapter extends RecyclerView.Adapter<ReferItemAdapter.viewHolder> implements ITouchHelperAdapter {
//长按拖动时变更项目的索引位置,swap的方式是直接交换,此处采用拖动插入的方式执行
@Override
public void onItemMove(int fromPosition, int toPosition) {
//Collections.swap(lstItems, fromPosition, toPosition);
ReferItemEntity referItem = lstItems.get(fromPosition);
lstItems.remove(referItem);
lstItems.add(toPosition, referItem);
notifyItemMoved(fromPosition, toPosition);
}
//侧滑删除后从列表中移除item并通过adapter更新移除
//先执行数据库删除否则position会因发生变化而删除错误
@Override
public void onItemSwip(int position) {
itemRemoveListener.onRemove(position);
lstItems.remove(position);
notifyItemRemoved(position);
}
//通过返回true或false来控制是否允许侧滑删除
@Override
public boolean canSwip() {
if(lstItems.get(0).getItem_type().equals("charge_tag")) return true;
else return false;
}
}
以上方法中定义了一个 itemRemoveListener 接口的回调 onRemove方法以便在Activity中执行数据库方面的删除操作
interface OnRVItemRemoveListener{
void onRemove(int position);
}
private IAdapter.OnRVItemRemoveListener itemRemoveListener;
public void setItemRemoveListener(IAdapter.OnRVItemRemoveListener listener) {
this.itemRemoveListener = listener;
}
Activity中通过 new IAdapter.OnRVItemRemoveListener() 的方式实现具体的 onRemove() 方法内容
因为实例化Adapter时传入的是List<>列表对象,内外列表指向同一堆上地址,所以内外变更时列表会同步更新
referItemAdapter.setItemRemoveListener(position -> {
//通知Presenter执行数据库删除
mPresenter.itemDelete(lstItems.get(position));
});