带有 RecyclerView 的 CoordinatorLayout:onScroll

Posted

技术标签:

【中文标题】带有 RecyclerView 的 CoordinatorLayout:onScroll【英文标题】:CoordinatorLayout with RecyclerView: onScroll 【发布时间】:2015-09-29 20:52:40 【问题描述】:

我有一个 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 for collapsable toolbars。现在向上滚动时,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 拦截的滚动更改?行为是正确的方式吗?

【问题讨论】:

【参考方案1】:

您是否尝试过添加一个 touchEvent 侦听器,然后为父视图组持有者停用拦截器事件?我认为这会将您想要处理的任何触摸事件的控制权返回给孩子。

    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;
          
       );

【讨论】:

【参考方案2】:

您应该改用ItemTouchHelper,详见this blog post。

它包含诸如

之类的方法 onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int)

这允许您在不编写自定义行为或触摸事件处理的情况下实现拖放以及滑动关闭。

【讨论】:

这是一个很好的博客,但它并没有为我的问题提供解决方案。协调器布局是根视图,正在拦截我的触摸。那是用于滑动和拖动的,我让它们工作得很好。我需要解决 Scrolling 没有被传递给 recyclerView。 嗯,不,你没有让一切正常工作:否则你根本不会有问题。使用ItemTouchHandler 删除滑动/拖动代码时,您会轻松很多,这与CoordinatorLayout 和嵌套滚动配合得很好。 我刚刚实现了这个,我遇到了我之前遇到的same问题。这证明问题在于协调器布局,而不是回收器视图。 @ChadBingham 你有什么运气吗?这是一个协调器布局问题。当我向上滚动时,我的情况有时我的项目会被解雇。如果我进行对角线滑动,我的物品会继续消失 @Mr.Noob 不,我运气不好。我看到一个关于这个问题的错误报告。所以我不得不删除协调器布局,直到他们修复它。我确实看到刚刚发布了更新,所以也许修复程序就在那里。但我没有检查。

以上是关于带有 RecyclerView 的 CoordinatorLayout:onScroll的主要内容,如果未能解决你的问题,请参考以下文章

我无法从另一个带有 recyclerview.adaper 的片段中打开带有 recyclerview.adapter 的片段

带有 RecyclerView 和折叠标题的 CoordinatorLayout

带有片段的 RecyclerView

带有水平溢出的Android垂直recyclerview

带有 ItemDecoration 的 RecyclerView 分隔线宽度

使用带有卡片的 RecyclerView