RecyclerView配合ItemTouchHelper的使用

temTouchHelper,可以很好的處理RecyclerView的item的滑動拖拽功能。
ItemTouchHelper是android.support.v7.widget.helper包中的一個類,但現在android官方文檔搜索,你會發現有兩個ItemTouchHelper,其中是這個包下,另一個是androidx.recyclerview.widget包下的,根據官網說法androidx是新推出的軟件包結構,一下support包都向androidx下遷移。不過現在support現在還是可以用的,Google給開發者一定的遷移時間。
在這裏插入圖片描述
ItemTouchHelper的構造方法需要傳入ItemTouchHelper.Callback來實現對拖拽的監聽。
現在就來看看ItemTouchHelper.Callback的一些方法
ItemTouchHelper.Callback是一個抽象類或者匿名內部類實現它,都必須實現它下面幾個抽象方法

//拖拽的標誌
 public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
 //移動的監聽
 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
 // 滑動的回調
 public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

簡單的使用

長按可以進行拖拽交換位置,左右可以滑動刪除
在這裏插入圖片描述

適配器代碼

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
    private ArrayList<String> lists;

    public RecyclerViewAdapter(ArrayList<String> lists) {
        this.lists = lists;
    }
    
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycle, parent, false);
        return new MyViewHolder(view);
    }
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tv.setText(lists.get(position));
    }

    @Override
    public int getItemCount() {
        return lists.size();
    }


    /** 刪除數據
     * @param position
     */
    public final void delData(int position) {
        lists.remove(position);
        notifyItemRemoved(position);
    }

    /** 移動進行數據交換
     * @param fromPosition 
     * @param toPosition
     */
    public final void move(int fromPosition, int toPosition) {
        Collections.swap(lists, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
    }
    
    class MyViewHolder extends RecyclerView.ViewHolder {
         AppCompatTextView tv;

        private MyViewHolder(View itemView) {
            super(itemView);
            tv = itemView.findViewById(R.id.tv);
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private RecyclerViewAdapter recyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recycler_view);
        //模擬數據
        ArrayList<String> lists = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            lists.add("item" + i);
        }
        recyclerViewAdapter = new RecyclerViewAdapter(lists);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(recyclerViewAdapter);
        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
            /**
             *
             * @param recyclerView 關聯的recyclerView
             * @param viewHolder  操作的viewHolder對象
             * @return 返回運動方向標誌的組合,通過makeMovementFlags(dragFlags, swipeFlags)進行組合
             */
            @Override
            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                //拖拽的方法標記
                int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
                //滑動方向標記
                int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
                //通過makeMovementFlags方法將將方向標記進行組合,並將複合的值返回
                return makeMovementFlags(dragFlags, swipeFlags);
            }

            /**
             * @param recyclerView 關聯的recyclerView
             * @param viewHolder  要移動的viewHolder對象
             * @param target   移動到的目標ViewHolder對象
             * @return 返回true 纔會執行ItemTouchHelper.Callback的onMoved方法,
             */
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                recyclerViewAdapter.move(viewHolder.getAdapterPosition(), target.getAdapterPosition());
                return true;
            }

            /**
             * @param viewHolder 滑動的viewHolder對象
             * @param direction  移動的方向標識
             */
            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                recyclerViewAdapter.delData(viewHolder.getAdapterPosition());
            }
        });
	    //關聯RecyclerView
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }
}

如果想操作item條目是想讓條目高亮怎麼辦,如下面效果?

在這裏插入圖片描述
想實現這種效果就要重寫ItemTouchHelper.Callback的兩個方法

// 拖拽或者滑動時調用
 public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)
 //拖拽或者滑動結束後調用
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 

具體實現

            /**
             * @param viewHolder  操作的ViewHolder對象
             * @param actionState  當前的狀態, ItemTouchHelper.ACTION_STATE_IDLE,閒置狀態
             *                     ItemTouchHelper.ACTION_STATE_SWIPE,開始滑動狀態
             *                     ItemTouchHelper.ACTION_STATE_DRAG,開始拖拽
             */
            @Override
            public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
                //如果不是現實狀態
                if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
                    //設置背景顏色爲藍色
                    viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getResources().getColor(android.R.color.holo_blue_light));
                    if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
                        RecyclerViewAdapter.MyViewHolder myViewHolder = (RecyclerViewAdapter.MyViewHolder) viewHolder;
                        //設置字體爲白色
                        myViewHolder.tv.setTextColor(Color.WHITE);
                    }
                }
                super.onSelectedChanged(viewHolder, actionState);
            }

            /** 還原狀態
             * @param recyclerView
             * @param viewHolder
             */
            @Override
            public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                viewHolder.itemView.setBackgroundColor(Color.TRANSPARENT);
                if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
                    RecyclerViewAdapter.MyViewHolder myViewHolder = (RecyclerViewAdapter.MyViewHolder) viewHolder;
                    myViewHolder.tv.setTextColor(Color.BLACK);
                }
                super.clearView(recyclerView, viewHolder);
            }

上面代碼可以看到在onSelectedChanged 中獲得viewHolder對象,就可以對RecyclerView的條目進行一些操作,如上面背景顏色的改變,還可以設置條目的一些動畫效果,當然一定要記得再clearView 還原條目的改變,否則回出現一些奇怪的情況,因爲RecyclerView條目是View是複用的。

非長按拖拽效果

ItemTouchHelper 默認是長按觸發拖拽,當然我們可以設置非長按拖拽效果,例如按住一個圖片進行拖拽
在這裏插入圖片描述

實現方法
1 在適配器重寫這個圖片的OnTouchListener方法

 @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        holder.tv.setText(lists.get(position));
//設置holder.img 的OnTouchListener方法
        holder.img.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                //dragListener 是適配器內部接口
                    if (dragListener != null) {
                        dragListener.onDrag(holder);
                    }
                }
                return false;
            }
        });
    }
 public interface DragListener {
        /**
         * 使用接口回調的方式將ViewHolder返回
         * @param holder
         */
        void onDrag(MyViewHolder holder);
    }

    private DragListener dragListener;

    public void setDragListener(DragListener dragListener) {
        this.dragListener = dragListener;
    }

2 在MainActivity中設置接口回調

 recyclerViewAdapter.setDragListener(new RecyclerViewAdapter.DragListener() {
            @Override
            public void onDrag(RecyclerViewAdapter.MyViewHolder holder) {
            // 手動的條用ItemTouchHelper的開始拖拽方法
                itemTouchHelper.startDrag(holder);
            }
        });
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章