嵌套的RecyclerView.如何防止子级RecyclerView滚动时父级RecyclerView滚动? [英] Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?
问题描述
我正在尝试实现水平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,
-
父
-
setNestedScrollingEnabled(false)
- 在子级
recyclerview
的onTouch()
中,我通过调用requestdisallowinterceptTouchevent(false)
禁用了父级
recyclerview
上的recyclerview
上的触摸事件
setNestedScrollingEnabled(false)
on the parentrecyclerview
- In the
onTouch()
of the childrecyclerview
I disable touch events on the parentrecyclerview
by calledrequestdisallowinterceptTouchevent(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;
}
}
并将其设置为子RecyclerView
的layoutManger
:
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屋!