RecyclerView is powerful because it is highly customizable. Due to this advantage, most of the current projects use RecyclerView. Here we imitate the function of QQ to realize drag and slide function of RecyclerView.
Function description
Drag up and down to realize the exchange of Item
Slide left and right to delete Item
On this basis, some additional interaction functions are added.
Implementation process
First, simulate the data. You need a bean file to store the data.
public class MyMessage { private int logo; private String name; private String lastMsg; private String time; public MyMessage(int logo, String name, String lastMsg, String time) { this.logo = logo; this.name = name; this.lastMsg = lastMsg; this.time = time; } public int getLogo() { return logo; } public void setLogo(int logo) { this.logo = logo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLastMsg() { return lastMsg; } public void setLastMsg(String lastMsg) { this.lastMsg = lastMsg; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } @Override public String toString() { return "MyMessage [logo=" + logo + ",name=" + name + ",lastMsg=" + lastMsg + ",time=" + time + "]"; } }
Then prepare the data, and use the static method to simulate the data directly.
public class DataUtils { public static List<MyMessage> init(){ List<MyMessage> list = new ArrayList<MyMessage>(); list.add(new MyMessage(R.drawable.logo, "Test No. 1", "Test content","01:34")); list.add(new MyMessage(R.drawable.logo, "Test No. two", "Test content","09:41")); list.add(new MyMessage(R.drawable.logo, "Test No. three", "Test content","11:28")); list.add(new MyMessage(R.drawable.logo, "Test No. four", "Test content","12:22")); list.add(new MyMessage(R.drawable.logo, "Test No. five", "Test content","15:25")); list.add(new MyMessage(R.drawable.logo, "Test No. six", "Test content","17:22")); list.add(new MyMessage(R.drawable.logo, "Test No. seven", "Test content","19:59")); list.add(new MyMessage(R.drawable.logo, "Test No. eight", "Test content","20:17")); list.add(new MyMessage(R.drawable.logo, "Test No. nine", "Test content","22:30")); list.add(new MyMessage(R.drawable.logo, "Test No. ten", "Test content","23:01")); return list; } }
Add action refresh callback interface
public interface ItemTouchMoveListener { //Drag callback, drag effect refresh boolean onItemMove(int fromPosition,int toPosition); //Side slip callback, side slip effect refresh boolean onItemRemove(int position); }
Add drag-and-drop callback interface
public interface StartDragListener { void onStartDrag(ViewHolder viewHolder); }
Implementing adapters and overwriting the required methods
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements ItemTouchMoveListener{ private StartDragListener dragListener; private List<MyMessage> list; public MyAdapter(StartDragListener dragListener, List<MyMessage> list) { this.list = list; this.dragListener = dragListener; } @Override public boolean onItemMove(int fromPosition, int toPosition) { //Data exchange Collections.swap(list,fromPosition,toPosition); //Refresh notifyItemMoved(fromPosition,toPosition); return true; } @Override public boolean onItemRemove(int position) { //Delete data list.remove(position); //Refresh interface notifyItemRemoved(position); return true; } class MyViewHolder extends RecyclerView.ViewHolder { private ImageView iv_logo; private TextView tv_name; private TextView tv_msg; private TextView tv_time; public MyViewHolder(View itemView) { super(itemView); iv_logo = (ImageView) itemView.findViewById(R.id.iv_logo); tv_name = (TextView) itemView.findViewById(R.id.tv_name); tv_msg = (TextView) itemView.findViewById(R.id.tv_lastMsg); tv_time = (TextView) itemView.findViewById(R.id.tv_time); } } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); View view = layoutInflater.inflate(R.layout.item_list, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } @Override public void onBindViewHolder(final MyViewHolder holder, int position) { MyMessage message = list.get(position); holder.iv_logo.setImageResource(message.getLogo()); holder.tv_name.setText(message.getName()); holder.tv_msg.setText(message.getLastMsg()); holder.tv_time.setText(message.getTime()); //Monitor logo touch events and use touch drag holder.iv_logo.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { //Pass it to callback dragListener.onStartDrag(holder); } return false; } }); } @Override public int getItemCount() { return list.size(); } }
Callback handling callback actions
public class MyItemTouchHelperCallback extends Callback { private static final String TAG = "MyItemTouchHelperCallba"; private ItemTouchMoveListener moveListener; public MyItemTouchHelperCallback(ItemTouchMoveListener moveListener) { this.moveListener = moveListener; } //Callback first to determine the current action @Override public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { //Monitor towing direction int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //Monitoring Side Slip Direction int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; int flags = makeMovementFlags(dragFlags, swipeFlags); return flags; } @Override public boolean isLongPressDragEnabled() { //Is dragging allowed return true; } //Callback while moving @Override public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) { //Call the adapter.notifyItemMoved(from,to) method to refresh the interface if (viewHolder.getItemViewType() != target.getItemViewType()) { return false; } //exchange boolean result = moveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return result; } //Callback during sideslip @Override public void onSwiped(ViewHolder viewHolder, int direction) { //Delete data moveListener.onItemRemove(viewHolder.getAdapterPosition()); } //Selected status @Override public void onSelectedChanged(ViewHolder viewHolder, int actionState) { if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { viewHolder.itemView.setBackgroundColor(Color.BLUE); } super.onSelectedChanged(viewHolder, actionState); } //recovery @Override public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) { viewHolder.itemView.setBackgroundColor(Color.WHITE); super.clearView(recyclerView, viewHolder); } //Dragging sideslip effect @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { float alpha = 1 - Math.abs(dX) / viewHolder.itemView.getWidth(); if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { //Transparency, XY scaling viewHolder.itemView.setAlpha(alpha); //viewHolder.itemView.setScaleX(alpha); //viewHolder.itemView.setScaleY(alpha); } if (alpha == 0) { viewHolder.itemView.setAlpha(1); //viewHolder.itemView.setScaleX(1); //viewHolder.itemView.setScaleY(1); } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }
Call in the main activity
public class MainActivity extends AppCompatActivity implements StartDragListener { private RecyclerView recyclerView; private ItemTouchHelper itemTouchHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(this)); List<MyMessage> list = DataUtils.init(); MyAdapter adapter = new MyAdapter(this, list); recyclerView.setAdapter(adapter); ItemTouchHelper.Callback callback = new MyItemTouchHelperCallback(adapter); itemTouchHelper = new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recyclerView); } @Override public void onStartDrag(RecyclerView.ViewHolder viewHolder) { itemTouchHelper.startDrag(viewHolder); } }
So far, dragging and sideslipping of RecycleView have been completed. The following figure is to achieve the effect.