说明:
1.实现这个效果的核心类是:ItemTouchHelper和ItemTouchHelper.Callbck.
2.mainActivity的布局就是一个recyclerview,item的布局cardview套着三个控件。
首先看MAinActivity的代码吧
public class MainActivity extends AppCompatActivity { List<String> list; RecyclerView recyclerView; MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.ry); list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add("我的序号是:" + i); } myAdapter = new MyAdapter(list); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(myAdapter); //1.创建item helper ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback); //2.绑定到recyclerview上面去 itemTouchHelper.attachToRecyclerView(recyclerView); //3.在ItemHelper的接口回调中过滤开启长按拖动,拓展其他操作 } //itemHelper的回调 ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() { /** * 官方文档的说明如下: * o control which actions user can take on each view, you should override getMovementFlags(RecyclerView, ViewHolder) * and return appropriate set of direction flags. (LEFT, RIGHT, START, END, UP, DOWN). * 返回我们要监控的方向,上下左右,我们做的是上下拖动,要返回都是UP和DOWN * 关键坑爹的是下面方法返回值只有1个,也就是说只能监控一个方向。 * 不过点入到源码里面有惊喜。源码标记方向如下: * public static final int UP = 1 0001 * public static final int DOWN = 1 << 1; (位运算:值其实就是2)0010 * public static final int LEFT = 1 << 2 左 值是3 * public static final int RIGHT = 1 << 3 右 值是8 */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //也就是说返回值是组合式的 //监控左右侧滑的方法swipFlag=ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT; int swipFlag = ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT; //监控上下滑动的方法dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int dragflag = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //等价于:0001&0010;多点触控标记触屏手指的顺序和个数也是这样标记哦 //makeMovementFlags (int dragFlags, int swipeFlags),看下面的解释说明 return makeMovementFlags(dragflag,swipFlag); /** * 备注:由getMovementFlags可以联想到setMovementFlags,不过文档么有这个方法,但是: * 有 makeMovementFlags (int dragFlags, int swipeFlags) * Convenience method to create movement flags.便捷方法创建moveMentFlag * For instance, if you want to let your items be drag & dropped vertically and swiped left to be dismissed, * you can call this method with: makeMovementFlags(UP | DOWN, LEFT); * 这个recyclerview的文档写的简直完美,示例代码都弄好了!!! * 如果你想让item上下拖动和左边滑动删除,应该这样用: makeMovementFlags(UP | DOWN, LEFT) */ //拓展一下:如果只想上下的话:makeMovementFlags(UP | DOWN, 0),标记方向的最小值1 } /** * 官方文档的说明如下 * If user drags an item, ItemTouchHelper will call onMove(recyclerView, dragged, target). Upon receiving this callback, * you should move the item from the old position (dragged.getAdapterPosition()) to new position (target.getAdapterPosition()) * in your adapter and also call notifyItemMoved(int, int). * 拖动某个item的回调,在return前要更新item位置,调用notifyItemMoved(draggedPosition,targetPosition) * viewHolde:正在拖动item * target:要拖到的目标 * @return true 表示消费事件 */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { //直接按照文档来操作啊,这文档写得太给力了,简直完美! myAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); //注意这里有个坑的,itemView 都移动了,对应的数据也要移动 Collections.swap(list, viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } /** * 谷歌官方文档说明如下: * 这个看了一下主要是做左右拖动的回调 * When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls onSwiped(ViewHolder, int). * At this point, you should update your adapter (e.g. remove the item) and call related Adapter#notify event. * @param viewHolder * @param direction */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //滑动处理 list.remove(viewHolder.getAdapterPosition()); myAdapter.notifyItemRemoved(viewHolder.getAdapterPosition()); } /** * 官方文档如下:返回true 当前tiem可以被拖动到目标位置后,直接”落“在target上,其他的上面的tiem跟着“落”, * 所以要重写这个方法,不然只是拖动的tiem在动,target tiem不动,静止的 * Return true if the current ViewHolder can be dropped over the the target ViewHolder. * @param recyclerView * @param current * @param target * @return */ @Override public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder current, RecyclerView.ViewHolder target) { return true; } /** * 官方文档说明如下: * Returns whether ItemTouchHelper should start a drag and drop operation if an item is long pressed. * 是否开启长按 拖动 * @return */ @Override public boolean isLongPressDragEnabled() { //return true后,可以实现长按拖动排序和拖动动画了 return true; } }; }
ItemTouchHelper的方法讲解都在注释中
adapter很简单item也只是一行text
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { List<String> list; public MyAdapter(List<String> list) { this.list = list; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_adapter,parent,false); MyViewHolder holder = new MyViewHolder(view); return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.textView.setText(list.get(position)); } @Override public int getItemCount() { return list == null ? 0 : list.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { TextView textView; public MyViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_serial_number); } } }