RecyclerView爱恨情仇之ItemTouchHelper

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z2464342708m/article/details/73088001

前几天,产品需求说要做一个数据列表拖拽效果,本来想着用ViewDragHelper来实现的,但是鉴于对滑动冲突处理的不咋地,就在网上找了其他的资料。发现了一个工具类库:ItemTouchHelper,这个类库配合RecyclerView,很优雅的实现数据数据增删,并伴随动画效果,拖拽排序等辅助功能。
至于这个辅助类库如何使用我就不再多说,网上的众多博客写的比我还好,在这主要来分享一下在开发过程中遇到的问题,并且提出解决方案。
一、这个问题需要注意一点细节,当设置RecyclerView的高度为wrap_content的时候,拖拽RecyclerView item,item拖拽的位置超出RecyclerView控件所占的位置时,会抛出数组越界异常,这个问题出现的主要原因是:假设RecyclerView数据只有两个item,当拖拽其中一个item至这两个item的位置之外时,RecyclerView会认为拖拽的item在第三个或者其他item所在的位置上,而目前只有两个item,下标超出了item的个数,报出了数据越界异常;
解决方案:

try {
   // FIXME: 2017/6/8 这里需要try catch一下,在Collections调用swap方法的时候,会报出数组越界异常
   //滑动事件
   MyLog.d("老地方:" + viewHolder.getAdapterPosition() + "\r\n" + "新地方:" + target.getAdapterPosition());
   Collections.swap(mAdapter.getItems(), viewHolder.getAdapterPosition(), target.getAdapterPosition());
   mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    } catch (Exception e) {
        e.printStackTrace();
    }

二、这个问题可能不是必现的,但是出现的几率还是比较大的,当拖拽一个item的时候,可能拖拽的这个item会于其他的item重叠在一起。当我发现这个问题的同时,我发现了另外一个现象,此时,点击非RecyclerView区域的时候,一切都可以恢复正常。做个假设,是不是在更新数据的时候出现了什么问题?那去更新一下适配器?好主意。尝试着onMove在个方法里面更新适配器,但是,貌似这样会有问题,那就是item每次只能拖拽一个item的间距。不过,可喜的是,不会出现item重叠的问题了。那好吧,拖拽动作是在按下屏幕之后开始进行,在离开屏幕之后结束。那么只要在手指离开去更新就行了。听起来貌似不错,试试呗。
解决方案:

rvTaskList.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (null != v && v instanceof RecyclerView && MotionEvent.ACTION_UP == event.getAction()) {
             mAdapter.UpdataTaskOrder();
             MyLog.d("拖拽结束,更新任务列表");
                 return true;
             }
             return false;
        }
   });

这个方法有点笨,这是我没发现ItemTouchHelper已经提供了拖拽结束是的回调的做法,我们可以直接调用这个回调就OK了:

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
       super.clearView(recyclerView, viewHolder);
       mAdapter.UpdataTaskOrder();
       MyLog.d("拖拽结束,更新任务列表");
}

三、这个问题有点特殊。当RecyclerView中的数据可以铺满一屏时,拖动第一个item,item会迅速移动到最后一屏相对应的位置,而对于其他位置的item来说是不会发生这样的现象,比如说:现在item移动到了第二个位置,马上item会移动到最后一屏的第二个位置。这个问题怎么解决呢。(本来想把gif图片上传上来,但是在上传的时候,页面卡住了,一直没上传上去,请各位见谅)
解决方案:根据上述现象可以了解到,只有处于position=0的item才会迅速移动,那么,我们把数据是配到除position=0的位置上是不是就可以解决了呢?
经过测试,这种解决方案确实可以解决拖拽滑动混乱的问题,目前也是使用这种方案解决的,如果各位博友们有更好的解决方案,欢迎分享。

猜你喜欢

转载自blog.csdn.net/z2464342708m/article/details/73088001