[Android] Drag & Drop, Swipe to dissmiss Recyclerview

Đăng bởi: Admin | Lượt xem: 1993 | Chuyên mục: Android

Chắc hẳn các bạn đã nhìn thấy hoặc sử dụng rất nhiều thư viện cho phép kéo thả (dra g& drop) hay vuốt để xóa item (swipe to dismiss) của RecyclerView. Có bao giờ các bạn tự hỏi làm sao để chúng có thể kéo thả mượn mà, đẹp mắt như vậy không? Trong bài viết này chúng ta sẽ cùng tìm hiểu cách làm 1 Recyclerview như vậy nhé.


Ví dụ về Drag & Drop, Swipe to dissmiss RecyclerView

1. Tìm hiểu ItemTouchHelper.Callback

Về cơ bản thì ItemTouchHelper.Callback là một abstract class, cung cấp 3 abstract menthod chính là:

1.1.  getMovementFlags

getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder);

Trả về giá trị là một số nguyên, định nghĩa cờ cho phép di chuyển item ở mỗi state. Default là ACTION_STATE_IDLE = 0 - Không cho phép drag & drop.

Bạn có thể trả về flag thông qua 2 method chính mà ItemTouchHelper cung cấp là makeMovementFlags(int, int)makeFlag(int, int)

Ở ví dụ của mình mình đã sử dụng menthod makeMovementFlags

 @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlag = ItemTouchHelper.LEFT;
        return makeMovementFlags(dragFlag, swipeFlag);
    }

Ở đây mình cho phép người dùng có thể Drag Lên và xuống, và cho phép người dùng vuốt sang trái để dissmiss. Nếu muốn cho phép người dùng vuốt sang phải để dissmiss thì mình khai báo ItemTouchHelper.RIGHT còn muốn cả trái và phải thì sử dụng ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT

1.2. onMove

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

Menthod này được gọi khi người dùng kéo 1 item từ vị trí này đến vị trí khác.

  • viewHolder là viewHolder của Item hiện tại đang được kéo
  • target là viewHolder của item đang được kéo tới. Bạn có thể dễ dàng xác định vị trí của 2 item này bằng cách sử dụng menthod getAdapterPosition của ViewHolder.

3. onSwiped

onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

Trả về khi một item của recyclerview bị biến mất khi swipe.

  • viewHolder là ViewHolder của item vừa dissmiss
  • direction là hướng dissmiss của item, có 2 kiểu dissmiss là START - Phải qua trái và END - Trái qua phải.

2. Tạo interface lắng nghe sự kiện drag & drop, swipe : ItemTouchListenner

Để dễ dàng bắt được sự kiện swipe drag & drop, chúng ta tạo ra 1 listenner để lắng nghe các event đó

ItemTouchListenner.java

public interface ItemTouchListenner {
    void onMove(int oldPosition, int newPosition);

    void swipe(int position, int direction);
}

3. Gắn sự kiện drag & drop trong ItemTouchHelper.Callback

Chúng ta sẽ custom class ItemTouchHelper.Callback để nhận sự kiện swipedrag & drop

SimpleItemToucHelperCallback.java

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
    private ItemTouchListenner mListenner;

    public SimpleItemTouchHelperCallback(ItemTouchListenner mListenner) {
        this.mListenner = mListenner;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return super.isLongPressDragEnabled();
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return super.isItemViewSwipeEnabled();
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlag, swipeFlag);
    }

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

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mListenner.swipe(viewHolder.getAdapterPosition(), direction);
    }
}

Như vậy là mỗi khi người dùng kéo thả hoặc vuốt thì mListenner sẽ báo về cho chúng ta thông qua 2 menthod swipe onMove chúng ta chỉ cần update lai adapter khi có sự thay đổi về dữ liệu là được rất đơn giản phải không nào?

4. Gắn ItemTouchHelper cho Recyclerview

Để gắn ItemToucherHelper chúng ta sử dụng menthod attackToRecyclerView(RecyclerView view) của lớp ItemTouchHelper

ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(new ItemTouchListenner() {
            @Override
            public void onMove(int oldPosition, int newPosition) {
                mAdapter.onMove(oldPosition, newPosition);
            }

            @Override
            public void swipe(int position, int direction) {
                mAdapter.swipe(position, direction);
            }
        });
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerView);

Như vậy mỗi khi có sự kiện move swipe ta sẽ gọi tới menthod update giao diện của adapter.

5. Update lại adapter của RecyclerView khi có sự kiện thay đổi

Trong lớp adapter ta định nghĩa thêm 2 menthod để xử lý sự kiện là onMove swipe. Đổi chỗ vị trí các item khi drag & drop

public void onMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(mData, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(mData, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
    }

Xóa item khi swipe thành công:

    public void swipe(int position, int direction) {
        mData.remove(position);
        notifyItemRemoved(position);
    }

Trên đây là phần giới thiệu của mình về Swipe, Drag & Drop trong RecyclerView, rất mong sẽ giúp ích được cho các dự án của các bạn.

Cảm ơn các bạn đã đọc bài viết.

Chào thân ái và quyết thắng!

vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!



Khóa học liên quan

Khóa học: Android

Học Kotlin cơ bản
Số bài học:
Lượt xem: 17611
Đăng bởi: Admin
Chuyên mục: Android

Học lập trình Flutter cơ bản
Số bài học:
Lượt xem: 58512
Đăng bởi: Admin
Chuyên mục: Android

Lập trình Android cơ bản
Số bài học:
Lượt xem: 22990
Đăng bởi: Admin
Chuyên mục: Android