RecyclerView,项目滑动,java.lang.IllegalStateException

时间:2015-02-11 22:48:31

标签: android android-recyclerview

我的任务是在RecyclerView中实现项目水平项目滑动。由于ViewPager源代码和其他一些资源,我实际上完成了任务,但是在一个场景中存在问题。

我的SwipeableRecyclerView(从现在开始的SRV)扩展了RecyclerView并实现了RecyclerView.OnItemTouchListener来执行实际工作的魔法。它还定义了一个自定义接口SwipeListener,它定义了一些方法,最重要的(对于这个问题)是'onSwipe(View view,int position,boolean right)'。

我的活动提供了SRV接口的实现,当检测到滑动并触发侦听器方法时,它会执行以下操作:

  • 使用'view.animate()。translationX(translationX)'
  • 以正确的方向将项目/滑动视图移出屏幕
  • 上面开始的动画有一个监听器,在onAnimationEnd中,从适配器中删除指定位置的项目并调用adapter.notifyItemRemoved(position)
  • 结果是视图消失到刷卡侧,然后回收者用动画移除了行 - 所有这些实际上非常好用

当我快速滑动时有时会出现问题,就像第一个动画尚未完成时一样,我开始滑动另一行。有时,它会创建没有视图的“洞”/幻像行;有时,我得到以下例外:

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling

并且堆栈跟踪显示adapter.notifyItemRemoved()是导致异常的方法。

对于异常问题,事件序列如下(来自我的调试跟踪):

started  for position: 11
started  for position: 10
finished for position: 11
removing 11
removed  11
finished position: 10
removing 10

因此,两个完成动画都是一个接一个地启动,当其中一个删除了它的项目并调用notifyItemRemoved时,另一个完成并调用删除该项目。我不确定这是怎么回事,因为所有这些都发生在主线程上,实际上,但我想滚动也是在动画帧中完成的,并且由于第二次删除,它以某种方式需要新的计算。

所以,我在泡菜中,我不知道如何处理这个问题。实际上,我认为最简单的方法是在动画启动时禁用整个回收站视图的触摸,并在滚动完成后再次启用它们。我没有禁用SRV,但我尝试了setEnabled(false),可点击等等,但没有任何作用。

任何帮助?

2 个答案:

答案 0 :(得分:3)

您可以检查mRecyclerView.getItemAnimator().isRunning(),比当前答案更容易。虽然true,但MotionEvent不应触发任何删除。

答案 1 :(得分:2)

这最终对我有用:

  • 将一个swipingEnabled属性添加到SRV;如果为false,则onInterceptTouchEvent只调用父实现,有效禁用项目滑动
  • 在负责处理滑动手势的方法中添加此代码(如删除条目等):

    swipeableRecyclerView.setSwipingEnabled(false);
    
  • 将此代码添加到创建SRV的位置附近:

    swipeableRecyclerView.setItemAnimator(new DefaultItemAnimator() {
    
        @Override
        public void onRemoveFinished(RecyclerView.ViewHolder item) {
            swipeableRecyclerView.setSwipingEnabled(true);
        }
    });
    

    这只是扩展了默认项目动画,其中包含一个方法的实现,该方法在删除动画完成时调用。

现在,我的轻扫已被序列化了#39;并且没有例外。