嵌套的RecyclerView.如何防止子级RecyclerView滚动时父级RecyclerView滚动? [英] Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?

查看:524
本文介绍了嵌套的RecyclerView.如何防止子级RecyclerView滚动时父级RecyclerView滚动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现水平recyclerview,并且recyclerview的每个项目都将是具有网格布局的垂直recyclerview.我面临的问题是,当我尝试垂直滚动子级recyclerview时,有时父级recyclerview进行滚动并开始水平滚动.我尝试解决的方法是

I am trying to implement a horizontal recyclerview and each item of the recyclerview will be a vertical recyclerview with a grid layout. The problem that i am facing is that when I try to scroll the child recyclerview vertically sometimes the parent recyclerview takes the scroll and starts scrolling horizontally. The approaches I tried to fix this are,

    recyclerview 上的
  1. setNestedScrollingEnabled(false)
  2. 在子级recyclerviewonTouch()中,我通过调用requestdisallowinterceptTouchevent(false)
  3. 禁用了父级recyclerview上的触摸事件
  1. setNestedScrollingEnabled(false) on the parent recyclerview
  2. In the onTouch() of the child recyclerview I disable touch events on the parent recyclerview by called requestdisallowinterceptTouchevent(false)

以上解决方案均不能为该问题提供完美的解决方案.感谢您的帮助

None of the above solutions provide a perfect fix for the problem. Any help is appreciated

推荐答案

这个问题对我来说似乎很有趣.因此,我尝试实施,这就是我所达到的目标(您也可以在此处看到视频).

The problem seemed interesting to me. So I tried to implement and this is what I achieved (you can also see the video here) which is pretty smooth.

因此您可以尝试以下操作:

So you can try something like this:

定义CustomLinearLayoutManager扩展LinearLayoutManager就像这样:

public class CustomLinearLayoutManager extends LinearLayoutManager {

    public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public boolean canScrollVertically() {
        return false;
    }
}

,然后将此CustomLinearLayoutManager设置为您的父级RecyclerView.

and set this CustomLinearLayoutManager to your parent RecyclerView.

RecyclerView parentRecyclerView = (RecyclerView)findViewById(R.id.parent_rv);
CustomLinearLayoutManager customLayoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false);
parentRecyclerView.setLayoutManager(customLayoutManager);
parentRecyclerView.setAdapter(new ParentAdapter(this)); // some adapter

现在为孩子RecyclerView,定义自定义CustomGridLayoutManager扩展GridLayoutManager:

Now for child RecyclerView, define custom CustomGridLayoutManager extending GridLayoutManager:

public class CustomGridLayoutManager extends GridLayoutManager {

    public CustomGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CustomGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
    }

    public CustomGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
        super(context, spanCount, orientation, reverseLayout);
    }

    @Override
    public boolean canScrollHorizontally() {
        return false;
    }
}

并将其设置为子RecyclerViewlayoutManger:

childRecyclerView = (RecyclerView)itemView.findViewById(R.id.child_rv);
childRecyclerView.setLayoutManager(new CustomGridLayoutManager(context, 3));
childRecyclerView.setAdapter(new ChildAdapter()); // some adapter

因此,基本上,父级RecyclerView仅监听水平滚动,子级RecyclerView仅监听垂直滚动.

So basically parent RecyclerView is only listening to horizontal scrolls and child RecyclerView is only listening to vertical scrolls.

此外,如果您还想处理对角滑动(几乎不垂直或水平倾斜),则可以在父级 RecylerView中包含手势侦听器.

Along with that, if you also want to handle diagonal swipe (which is little skewed to either vertical or horizontal), you can include a gesture listener in the parent RecylerView.

public class ParentRecyclerView extends RecyclerView {

    private GestureDetector mGestureDetector;

    public ParentRecyclerView(Context context) {
        super(context);
        mGestureDetector = new GestureDetector(this.getContext(), new XScrollDetector());
       // do the same in other constructors
    }

   // and override onInterceptTouchEvent

   @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev);
    }

}

XScrollDetector在哪里

class XScrollDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return Math.abs(distanceY) < Math.abs(distanceX);
        }
}

因此,ParentRecyclerView要求子视图(在我们的示例中为VerticalRecyclerView)处理滚动事件.如果子视图可以处理,则父级不执行其他任何操作,父级最终可以处理滚动.

Thus ParentRecyclerView asks child view (in our case, VerticalRecyclerView) to handle the scroll event. If the child view handles then parent does nothing else parent eventually handles the scroll.

这篇关于嵌套的RecyclerView.如何防止子级RecyclerView滚动时父级RecyclerView滚动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆