RecyclerView借助ItemTouchHelper实现拖动排序功能

先上效果图

概述

RecyclerView 的显示实现这里就不说了,之前的文章有提到
Android中RecyclerView的简单实现
这里主要说下怎么实现这个拖动排序的功能
主要代码都在是 activity 里面实现

先初使化几个变量

这些变量主要是用来更新数据列表的,显示有简单的实现方法,但往往会出错,这里使用的方法虽然原始了一些,但可以保证 position 位置不会出错

private Boolean isFirstMove = true;
private int frmPosition = 0;

绑定拖动事件

这个比较简单,这也是RecyclerView的强大之处,只要实例化一个ItemTouchHelper,然后处理他的回调事件,就是拖动时的事件就可以了,不用再自己去计算坐标之类的

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(mView.rvDesktopAppsort);

自定义实现拖动事件

ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() {
    
    
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
    
    
        int swipFlag = 0; //滑动方向,这个主要是用来侧滑删除之类的操作,我这里用不到,就不实现了
        //这里的拖动方向可能根据自己的需要进行调整,如果是列表类的,那只要上下拖动就要以,因为我这里是gridview样式的,所以还会用到左右拖动
        int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //拖动方向
        return makeMovementFlags(dragFlag, swipFlag);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
    
    
    //这里只所以要记录下第一次滑动的位置,是因为滑动过程中会反复调用这个方法,导致得到的position一直在变,我这里只需要拖动项目的index和目标index就够了
		if (isFirstMove) {
    
    
            frmPosition = viewHolder.getAdapterPosition();
            isFirstMove = false;
        }
        //正常只要有下面这一句就可以看到拖动效果了,但后面列表的position会乱掉,所以处理起来就要稍稍变更一下了
        sortAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        //以下记得把列表也要更新。但使用此方法会有一个问题就是move方法会被反复调用导致无法正常更新列表
        //通过clearView的最后获取目标位置来进行更换
        //Collections.swap(lstApps, viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
    
    
		//这个主要是用来侧滑删除之类的操作,我这里用不到,就不实现了
    }
    
    //拖动完成之后调用,所操作的viewHolder即为目标位置的项目
    //为了得到目标项目的index 也要实现这个方法
    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
    
    
        super.clearView(recyclerView, viewHolder);
        int endPosition = viewHolder.getAdapterPosition();
        listSwap(lstApps, frmPosition, endPosition);
        isFirstMove = true;
    }
};

//更新列表
//本来打算使用swap的,但是这个拖动会让目标位置之间的元素全部发生位置变化,所以使用列表的移除和添加功能进行更新列表
private void listSwap(ArrayList<AppPackage> lstApp, int frm, int to){
    
    
    AppPackage appPackage = lstApp.get(frm);
    lstApp.remove(appPackage);
    lstApp.add(to, appPackage);
}

猜你喜欢

转载自blog.csdn.net/ymtianyu/article/details/109054143