iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Mobile Development

Android 開發 30天 初學之路筆記系列 第 13

Day13 - RecyclerView 進階操作 | 拖曳排序、左右刪除、復原操作

  • 分享至 

  • xImage
  •  

接續上一遍, 這次要講的是相對進階的操作:

  1. 上下拖曳 - 實現Item排序
  2. 左右滑動 - 實現刪除&封存操作
  3. 滑動後的復原操作

一、上下拖曳 - 實現Item排序

效果圖:

要實現拖曳, 需要重寫onMove方法。

public ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    ...
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        int fromPosition = viewHolder.getBindingAdapterPosition();
        int toPosition = target.getBindingAdapterPosition();

        Collections.swap(dataList, fromPosition, toPosition); //Item互換
        notifyItemMoved(fromPosition, toPosition); //通知Recyclerview Item被移動了

        return false;
    }
    ...
}

new ItemTouchHelper.SimpleCallback(dragDirs, swipeDirs)
需要傳入兩個參數:

  • dragDirs:表示可以拖曳的方向
  • swipeDirs:表示可以滑動的方向
  • 可傳入的方向常數:
    • ItemTouchHelper.UP
    • ItemTouchHelper.DOWN
    • ItemTouchHelper.LEFT
    • ItemTouchHelper.RIGHT

二、左右滑動 - 實現刪除&封存操作

效果圖:

要實現滑動,需要重寫onSwiped方法。

private List<String> archivedItems = new ArrayList<>(); // 用來紀錄右滑被封存的Item清單

public ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    ...
    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        int position = viewHolder.getBindingAdapterPosition();

        switch (direction) {
            // Item向左滑表示刪除
            case ItemTouchHelper.LEFT:
                dataList.remove(position);
                notifyItemRemoved(position); // 通知RecyclerView有Item被刪除了, 用以更新畫面
                break;
            // Item向右滑表示封存
            case ItemTouchHelper.RIGHT:
                String itemName = dataList.get(position);
                archivedItems.add(itemName);
                dataList.remove(position);
                notifyItemRemoved(position); // 通知RecyclerView有Item被刪除了, 用以更新畫面
                break;
        }
    }
}

左滑、右滑後面的背景圖顯示

在github上有位大神已經實現這樣的效果並提供簡單的API供使用,我們只需要把這個第三方套件導入自己的專案即可。跟著以下的步驟配置環境:

套件連結:https://github.com/xabaras/RecyclerViewSwipeDecorator

  • (一)在settings.gradle添加
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • (二) 在build.gradle(Module: app)添加依賴
dependencies {
    ...
    implementation 'com.github.xabaras:RecyclerViewSwipeDecorator:1.4'
}
  • 程式碼部分
    我們需要重寫onChildDraw來實現在滑動時, item後面呈現圖示的效果
public ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    ...

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        new RecyclerViewSwipeDecorator.Builder(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            .addSwipeLeftBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.item_delete))
            .addSwipeLeftActionIcon(R.drawable.ic_delete_24dp)
            .addSwipeRightBackgroundColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.item_archive))
            .addSwipeRightActionIcon(R.drawable.ic_archive_24dp)
            .create()
            .decorate();
        
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}

三、滑動後的復原操作

  • 效果圖
private String deletedItem = null; // 用來記錄左滑刪除的Item
private List<String> archivedItems = new ArrayList<>(); // 用來紀錄右滑被封存的Item清單

public ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    ...
        
    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        int position = viewHolder.getBindingAdapterPosition(); // 紀錄當前滑動的item位置

        switch (direction) {
            // Item向左滑表示刪除
            case ItemTouchHelper.LEFT:
                deletedItem = dataList.get(position);
                dataList.remove(position);
                notifyItemRemoved(position);
                // 復原操作提示
                Snackbar.make(viewHolder.itemView, deletedItem + " 已被刪除", Snackbar.LENGTH_LONG)
                        .setAction("復原", (view) -> {
                                    dataList.add(position, deletedItem);
                                    notifyItemInserted(position);
                                }
                        ).show();
                break;
            // Item向右滑表示封存
            case ItemTouchHelper.RIGHT:
                String itemName = dataList.get(position);
                archivedItems.add(itemName);
                dataList.remove(position);
                notifyItemRemoved(position);
                // 復原操作提示
                Snackbar.make(viewHolder.itemView, itemName + " 已被封存", Snackbar.LENGTH_LONG)
                        .setAction("復原", (view) -> {
                                    dataList.add(position, itemName);
                                    archivedItems.remove(archivedItems.indexOf(itemName));
                                    notifyItemInserted(position);
                                }
                        ).show();
                break;
        }
    }
    ...
}

上一篇
Day12 - RecyclerView 簡單使用
下一篇
Day14 - 常用的9種對話框(Dialog)
系列文
Android 開發 30天 初學之路筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言