您的位置:首页 > 其它

Recyclerview条目可拖拽可侧滑删除实战详解

2017-04-23 10:13 387 查看
先看效果图



要实现这种效果,Android提供的有相关Api:ItemTouchHelper, 它是继承ItemDecoration的, 它内部有一个静态的抽象类

public abstract static class Callback


首先我们需要准备一个recyclerview的列表数据

[下面开始正文]

我们需要重写ItemTouchHelper.Callback这个抽个抽象类,并需要重写三个方法:

getMovementFlags : 主要通过这个方法,我们能拿到一个方向

onMove:拖动时回调这个函数

onSwiped : 侧滑回调这个函数

public class WolfItemTouchHelperCallback extends Callback{
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

return 0;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

}
}


问题来了我们怎么知道它根据什么知道长按拖动还是侧滑删除呢?

所以我们还需要两个辅助方法用来判断是拖动还是侧滑:isLongPressDragEnabledisItemViewSwipeEnabled()

在这个ItemTouchHelper.Callback静态抽象内部类中有这两个方法

/**
* 可拖动返回true
* */
@Override
public boolean isLongPressDragEnabled() {
return true;
}

/**
* 可侧滑返回true
* */
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}


ItemTouchHelper.Callback与Adapter进行通信

目的是要adapter时刻知道列表发生了变化,以便及时刷新ui界面

这里我们定义一个接口进行通信,我们需要当ui界面发生拖动和侧滑事件后,把位置的变化信息传递给接口。然后adapter实现这个接口,就可以从里面获取位置信息了,这样就可以及时刷新ui界面了!

//定义的接口
public interface ItemHelper {
//拖动
void onItemMove(int frompos,int topos);
//侧滑
void onItemDimss(int topos);
}


看完整WolfItemTouchHelperCallback.java

public class WolfItemTouchHelperCallback extends ItemTouchHelper.Callback {

/**
* 第一步重写这三个方法
* getMovementFlags
* onMove
* onSwiped
* 第二步重写这三个方法后我们还需要两个帮助函数
* isLongPressDragEnabled 和
* isItemViewSwipeEnabled
* 第三步自定义接口作为WolfItemTouchHelperCallback和Adapter通信的桥梁,在构造方法中声明这个接口
*
* */
private ItemHelper itemHelper;
public WolfItemTouchHelperCallback(ItemHelper itemHelper){
this.itemHelper=itemHelper;
}

/**
* 获取一个方向
* */
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//up  down  既能向上拖拽也能向下拖拽
int up_down_drags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipes  = ItemTouchHelper.START | ItemTouchHelper.END;
Log.e("getMovementFlags","getMovementFlags");
return makeMovementFlags(up_down_drags,swipes);
}

/**
* 拖动时调用
* */
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
/**
* 这个函数在拖动时调用
* 我们在拖动时,需要把拖动item的起始position,和要拖到到的位置的position,通知给adapter,让其刷新view
* 我们可以通过自定义接口来传递数据
* */
int adapterFrom_Position = viewHolder.getAdapterPosition();
int adapterTo_Position = target.getAdapterPosition();
Log.e("onMove","onMove");
//这里把位置信息传递给接口了
itemHelper.onItemMove(adapterFrom_Position,adapterTo_Position);
return true;
}

/**
* 侧滑时调用
* */
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int adapterPosition = viewHolder.getAdapterPosition();
Log.e("onSwiped","onSwiped");
itemHelper.onItemDimss(adapterPosition);

}

/**
* 可拖动返回true
* */
@Override
public boolean isLongPressDragEnabled() {
return true;
}

/**
* 可侧滑返回true
* */
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}

}


看完整WolfRecAdapter.java

public class WolfRecAdapter extends RecyclerView.Adapter<WolfRecAdapter.ViewHolder> implements ItemHelper{

public Context mCpntext;
public List mList;
private final LayoutInflater inflater;

public WolfRecAdapter(Context mCpntext, List mList){
thi
c983
s.mCpntext=mCpntext;
this.mList=mList;
inflater = LayoutInflater.from(mCpntext);

}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.item, parent, false);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.e("position","position"+position);
holder.tv.setText(mList.get(position)+"");

}

@Override
public int getItemCount() {
return mList.size();
}

/**
* 拖拽时
* */
@Override
public void onItemMove(int frompos, int topos) {
Object remove = mList.remove(frompos);
mList.add(topos > frompos ? topos - 1 : topos, remove);
Log.e("onItemMove","onItemMove");
//刷新view
notifyItemMoved(frompos,topos);
}

/**
* 侧滑
* */
@Override
public void onItemDimss(int topos) {
mList.remove(topos);
Log.e("onItemDimss","onItemDimss");
//移除
notifyItemRemoved(topos);

}

public class ViewHolder extends RecyclerView.ViewHolder{

private final TextView tv;

public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
}


最后在activity中的使用

//在设置玩适配器后可以这样写

//把adapter自定义的WolfItemTouchHelperCallback
ItemTouchHelper.Callback callback = new WolfItemTouchHelperCallback(wolfRecAdapter);
//把自定义的WolfItemTouchHelperCallback  传入到ItemTouchHelper
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);


到这里已经实现了可拖动可侧滑删除的功能了!

我们通过Log进一步分析下

我们打开app,不做任何操作,在当前界面显示的条目:



拖拽时:把第二个条目(position1)拖到第一个条目的位置(position0)



我们可以发现当我们触目条目时会调用getMovementFlags,确定是长按拖动时会依次调用:isLongPressDragEnabled-getMovementFlags-onMove-onItemMove(自定义的接口)

侧滑删除时:



之所以多次调用isItemViewSwipeEnabled是因为,只要我们滑动列表就会多次调用,我们点击时很难准确的点到一个点。getMovementFlags-onSwiped-onItemDimss。position也会发生变化,因为删除一个后面的肯定要补充一个位置。

通过这些log我们很明确的看到他的调用流程了!

Activity-WolfItemTouchHelperCallback-WolfRecAdapter刷新界面

demo免费下载:本人使用的as是2.3版本的

http://download.csdn.net/detail/qq_34501274/9822706
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息