CoordinatorLayout与RecyclerView:onScroll

5

我有一个RecyclerView,其中添加了可以对列表项执行的不同操作,特别是DragDropSwipeDismissDragDrop由长按发起,而SwipeDismiss则由滑动发起。我必须监听滚动事件以阻止这些操作的发生。在滚动时突然转换为拖动很让人烦恼。之前我会添加一个OnScrollListener来处理这个问题。

以下是我之前所做的:

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    if(newState == RecyclerView.SCROLL_STATE_IDLE){
        drag.setCurrentAction(IDLE);
    } else {
        drag.setCurrentAction(SCROLL);
    }
}

不再工作

最近我添加了可折叠工具栏的CoordinatorLayout。现在,当向上滚动时,drag直到工具栏被折叠后才会被设置为SCROLL。我试图创建自己的行为,但那将替换我正在使用的当前行为;@string/appbar_scrolling_view_behavior。这删除了我想要的工具栏行为,并且无法通知我的drag状态。


我试过的方法:

@Override
public boolean onStartNestedScroll(CoordinatorLayout cl, CollapsingToolbarLayout child, View directTargetChild,
        View target, int nestedScrollAxes) {

    if (nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL) {
        if (drag.getCurrentAction().ordinal() < SCROLL.ordinal()) {
            /* No actions have started and we are scrolling. set the new action */
            drag.setCurrentAction(SCROLL);
        }
        return true;
    }
    return super.onStartNestedScroll(cl, child, directTargetChild, target, nestedScrollAxes);
}

@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, CollapsingToolbarLayout child, View target) {
    super.onStopNestedScroll(coordinatorLayout, child, target);
    if (drag.getCurrentAction() == SCROLL) {
        drag.setCurrentAction(INVALID);
    }
}

所以我的问题是

如何监听被CoordinatorLayout拦截的recycler view滚动变化?使用Behavior是否是正确的方式?

2个回答

0

你尝试过添加一个touchEvent监听器,然后禁用父ViewGroup持有者的拦截器事件吗?我认为这会将任何你想要处理的触摸事件控制权返回给子元素。

    scrollView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
               // Disallow the touch request for parent scroll on touch of child view

                     v.getParent().requestDisallowInterceptTouchEvent(true);

                } else if (event.getAction() == MotionEvent.ACTION_UP) {

                      v.getParent().requestDisallowInterceptTouchEvent(false);
               }
          return false;
          }
       });

-1

你应该使用ItemTouchHelper,详见这篇博客文章

它包含了以下方法:

  • onMove(RecyclerView, ViewHolder, ViewHolder)
  • onSwiped(ViewHolder, int)

这些方法允许你实现拖放和滑动删除,而无需编写自定义的Behaviors或触摸事件处理。


1
这是一篇不错的博客,但它并没有提供解决我的问题的方法。CoordinatorLayout 是根视图,正在拦截我的触摸事件。而那是针对滑动和拖拽的,我已经成功地实现了这些功能。我需要解决的是无法将滚动事件传递给 RecyclerView。 - Chad Bingham
不,你没有完全做对:否则你就没有任何问题了。使用ItemTouchHandler删除滑动/拖动代码将会更加容易,而它与CoordinatorLayout和嵌套滚动非常兼容。 - ianhanniballake
1
我刚刚实现了这个,但是我仍然遇到了和之前一样的问题。这证明问题出在协调布局而不是回收视图上。 - Chad Bingham
1
@ChadBingham,你在这方面有什么进展了吗?这是一个协调布局问题。我的情况是当我向上滚动时,有时我的项目会被解除。如果我进行对角线滑动,我的项目就会一直被解除。 - Mr.Noob
1
@Mr.Noob 不,我没有什么运气。我看到有人报告了一个关于这个问题的错误。所以我不得不删除协调布局,直到他们修复它。我确实看到有一个更新刚刚发布,也许修复已经在那里了。但我还没有检查过。 - Chad Bingham
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接