RecyclerView的深入——ItemTouchHelper,实现侧滑删除和上下拖动交换位置

参考文献:https://blog.csdn.net/a553181867/article/details/54799391  (侵删)

今天在总结5.0与6.0新控件的时候发现了这个新的工具类,ItemTouchHelper,这个实现recyclerview侧滑删除与上下拖动交换位置的官方sdk,对此产生浓厚兴趣,于是开始学习了一下,首先来介绍一下ItemTouchHelper这个工具类,它包含了一下几种方法:

getMovementFlags  这个方法返回一个int值用于判断item是上下拖动还是侧滑删除,一般我们使用makeMovementFlags(int,int)或者makeFlag(int,int)来设置;

onMove 这个方法内设置当item移动的时候执行的操作,在里面执行移动方法,用于调换两个viewholder,设置移动的时候返回为true;

onSwiped 这个方法内执行当item打到删除条件的时候的方法;

isLongPressDragEnabled  这个方法设置是否长按触发拖动item,默认为true;

isItemViewSwipeEnabled 这个方法设置左右移动的时候调用onswiped方法,进行item的删除操作,默认返回true;

onSelectedChanged 当item由静止变为拖动状态时调用的方法,其中的actionState参数表示当前的item状态;

RecyclerView的深入——ItemTouchHelper,实现侧滑删除和上下拖动交换位置

这个方法我引用原文章的文献,因为我没有使用过这个方法,理解不深,不敢随便乱说,以后实践过后再来改动


onChildDraw 从方法名字可以看出是item产生变化时的动画效果

这里我在原文基础上加一个onChildDrawOver方法,这个方法在页面变化状态完成之后产生的动画效果

介绍完这些,我们先看看效果图:

RecyclerView的深入——ItemTouchHelper,实现侧滑删除和上下拖动交换位置

接下来上代码:

package com.example.administrator.recycleritemtouchhelper;

import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private List<String> list = new ArrayList<>();
    private String[] item_data = {"111", "222", "333"};
    private ItemTouchHelper itemTouchHelper;
    private ItemTouchHelper.Callback callback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        for (int i = 0; i < item_data.length; i++) {
            list.add(item_data[i]);
        }
        recyclerView = findViewById(R.id.recycler_mian);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        final MainAdapter mainAdapter = new MainAdapter();
        recyclerView.setAdapter(mainAdapter);
        callback = new ItemTouchHelper.Callback() {
            @Override
            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                int move = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
                int delete = ItemTouchHelper.LEFT;
                return makeMovementFlags(move, delete);
            }

            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                mainAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
                return true;
            }

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

        };
        itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }

    private class MainAdapter extends RecyclerView.Adapter<MainViewHolder> implements ItemTouchHelperAdapter {

        @NonNull
        @Override
        public MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false);
            return new MainViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull MainViewHolder holder, int position) {
            holder.setData(list.get(position));
        }

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

        @Override
        public void onItemMove(int startposition, int endposition) {
            Collections.swap(list, startposition, endposition);
            notifyItemMoved(startposition, endposition);
        }

        @Override
        public void onItemDelete(int position) {
            list.remove(position);
            notifyItemRemoved(position);
        }
    }

    private class MainViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;

        public MainViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.ietm_text);
        }

        private void setData(String data) {
            textView.setText(data);
        }
    }

    public interface ItemTouchHelperAdapter {
        void onItemMove(int startposition, int endposition);

        void onItemDelete(int position);
    }
}

现在来分析代码,ItemTouchHelper执行的移动和删除操作,其实就是Adapter里面的notifyItemMoved和notyfyItemRemoved方法,但是我们需要在ItemTouchHelper.CallBack中用到,所以我们将这两个方法在Adapter中写成单独的移动和移除方法:

public interface ItemTouchHelperAdapter {
    void onItemMove(int startposition, int endposition);

    void onItemDelete(int position);
}

然后在Adapter中引入这个方法,在方法中设置item的移除与移动操作:

@Override
public void onItemMove(int startposition, int endposition) {
    Collections.swap(list, startposition, endposition);
    notifyItemMoved(startposition, endposition);
}

@Override
public void onItemDelete(int position) {
    list.remove(position);
    notifyItemRemoved(position);
}

然后我们在onCreat方法中初始化ItemToucherHelper和ItemTouchHelper.callback,并且重写callback中的三个基础方法:

callback = new ItemTouchHelper.Callback() {
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int move = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int delete = ItemTouchHelper.LEFT;
        return makeMovementFlags(move, delete);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        mainAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

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

};

然后绑定callback和recyclerview:

itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);

就可以实现上面的功能啦!

这里要说一下,如果item侧滑删除过程中item超过了百分之五十的位置时离开触摸状态item会自动调用onswipe方法,如果没有的话会自动返回当前位置哦~



我是分割线---------------------------------------------------------------------------------------------------------------------

这里要说一下ItemMove中的Collections类,这个是集合工具类,这里的swep方法是将两个下标的子项交换,其余方法如下:

Collections.shuffle(List<?> list);//随机置换
Collections.sort(List<?> list,Comparator<? super T> c);//排序,可升序可降序
Collections.fill(List<? super ?>list, T object);//替换
Collections.min(List<?>list);//取最小值

Collections.max(List<?>list);//取最大值
Collections.reverse(List<?>list);//将数组反转
Collections.reverse(List<?>list,List<?>list1);//复制
还有可以通过synchronizedCollection方法获得线程安全的集合