首页 文章

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

提问于
浏览
3

我的任务是在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 回答

  • 2

    这最终对我有用:

    • 将一个swipingEnabled属性添加到SRV;如果为false,则onInterceptTouchEvent只调用父实现,有效地禁用项目滑动

    • 在负责处理滑动手势的方法中添加此代码(如删除条目等):

    swipeableRecyclerView.setSwipingEnabled(false);
    
    • 将此代码添加到创建SRV的位置附近:
    swipeableRecyclerView.setItemAnimator(new DefaultItemAnimator() {
    
        @Override
        public void onRemoveFinished(RecyclerView.ViewHolder item) {
            swipeableRecyclerView.setSwipingEnabled(true);
        }
    });
    

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

    现在,我的swipe-to-dismiss是'序列化',没有例外 .

  • 3

    您可以检查 mRecyclerView.getItemAnimator().isRunning() ,比当前答案更容易一些 . 虽然 trueMotionEvent 不应该触发任何删除 .

相关问题