說明:
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); } } }