RecycleView long press drag control ItemTouchHelper.Callback

1.Adapter

Inherit RecycleView.Adapter

In fact, it is not difficult to implement long-press and drag controls in RecycleView. Just rewrite ItemTouchHelper.Callback. ItemTouchHelper is a tool class that implements RecyclerView‘s side-sliding deletion and drag-and-drop movement.

The following code is the ordinary RecycleView.Adapter implementation process except ItemTouchHelper.Callback.

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.Holder>{
    private Context context;
    private ItemTouchHelper itemTouchHelper;
    public ItemAdapter(Context context) {
        this.context=context;
        itemTouchHelper = new ItemTouchHelper(callback);//Instantiate ItemTouchHelper
    }

    @NonNull
    @Override
    public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new Holder(LayoutInflater.from(context).inflate(R.layout.item, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull Holder holder, int position) {
        String text = position + "";
        holder.textView.setText(text);
    }


    @Override
    public int getItemCount() {
        return 10;
    }
    public ItemTouchHelper getItemTouchHelper(){
        return itemTouchHelper;
    }
    public static class Holder extends RecyclerView.ViewHolder{
        private TextView textView;

        public Holder(@NonNull View itemView) {
            super(itemView);
            textView=itemView.findViewById(R.id.textview);
        }
    }
    private final ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() {
// @Override
// public boolean isLongPressDragEnabled() {
// return true;
// }

        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            //Allow the component to move up and down, and slide to the left
            return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.LEFT);
        }

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

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


    };
}

Focus on the code that implements drag and drop:

 private final ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() {
// @Override
// public boolean isLongPressDragEnabled() {
// return true;
// }

        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            //Allow the component to move up and down, and slide to the left
            return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.LEFT);
        }

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

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


    };

These three methods must be rewritten

getMovementFlags

getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder)

Generally OK

return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.LEFT);

makeMovementFlags(int dragFlags, int swipeFlags)
dragFlags: The direction in which you can drag swipeFlags: The direction in which you can slide

onMove

onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target)

Called when dragging an item from its old location to its new location.

onSwiped

When the user slides to delete an item, the onSwiped() method will be called back.

2. Create an instance

Create an ItemTouchHelper.Callback instance and an ItemTouchHelper instance

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ItemAdapter itemAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycle_view);
        recyclerView = findViewById(R.id.recycle_view);
        itemAdapter = new ItemAdapter(this); //Instantiate adapter
        //RecyclerView and ItemTouchHelper are bound to each other
        itemAdapter.getItemTouchHelper().attachToRecyclerView(recyclerView);
        //Set adapter
        recyclerView.setAdapter(itemAdapter);
        //Set the LayoutManager, otherwise the item will not be displayed! ! !
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }
}

Realization renderings:

Left: initial image

Right: Slide 6 process diagram

I want to drag 6 below 9, but actually the left image will be restored after I let go. In other words, I only implemented dragging, and the position of the item cannot be changed.

3. Implement control position changes

rewrite

onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target)
 @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
            return true; //There is an article saying that the position cannot be exchanged after returning false. I tried it and I can exchange the position.
        }

Call notifyItemMoved() to swap positions.