嵌套的 RecyclerView.如何防止父 RecyclerView 在子 RecyclerView 滚动时滚动? [英] Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?
问题描述
我正在尝试实现一个水平的 recyclerview
,并且 recyclerview
的每一项都将是一个具有网格布局的垂直 recyclerview
.我面临的问题是,当我尝试垂直滚动子 recyclerview
时,有时父 recyclerview
接受滚动并开始水平滚动.我试图解决这个问题的方法是,
setNestedScrollingEnabled(false)
在父recyclerview
- 在子
recyclerview
的onTouch()
中,我通过调用requestdisallowinterceptTouchevent(false) 禁用了父
recyclerview
上的触摸事件
以上解决方案均无法完美解决问题.任何帮助表示赞赏
我觉得这个问题很有趣.所以我尝试实施,这就是我取得的成果(您也可以在
所以你可以尝试这样的事情:
定义 CustomLinearLayoutManager
扩展 LinearLayoutManager
像这样:
public class CustomLinearLayoutManager extends LinearLayoutManager {公共 CustomLinearLayoutManager(上下文上下文,整数方向,布尔反向布局){超级(上下文,方向,reverseLayout);}@覆盖公共布尔 canScrollVertically() {返回假;}}
并将此 CustomLinearLayoutManager
设置为您的父 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));//一些适配器
现在为子RecyclerView
,定义自定义CustomGridLayoutManager
扩展GridLayoutManager
:
public class CustomGridLayoutManager extends GridLayoutManager {公共 CustomGridLayoutManager(上下文上下文,AttributeSet attrs,int defStyleAttr,int defStyleRes){超级(上下文,属性,defStyleAttr,defStyleRes);}公共 CustomGridLayoutManager(上下文上下文,int spanCount){超级(上下文,spanCount);}public CustomGridLayoutManager(上下文上下文,int spanCount,int方向,boolean reverseLayout){超级(上下文,spanCount,方向,reverseLayout);}@覆盖公共布尔 canScrollHorizontally() {返回假;}}
并将其设置为layoutManger
给子RecyclerView
:
childRecyclerView = (RecyclerView)itemView.findViewById(R.id.child_rv);childRecyclerView.setLayoutManager(new CustomGridLayoutManager(context, 3));childRecyclerView.setAdapter(new ChildAdapter());//一些适配器
所以基本上父 RecyclerView
只听水平滚动,子 RecyclerView
只听垂直滚动.
除此之外,如果您还想处理对角滑动(几乎不偏向垂直或水平),您可以在 parent RecylerView
.
public class ParentRecyclerView extends RecyclerView {私有 GestureDetector mGestureDetector;公共 ParentRecyclerView(上下文上下文){超级(上下文);mGestureDetector = new GestureDetector(this.getContext(), new XScrollDetector());//在其他构造函数中做同样的事情}//并覆盖 onInterceptTouchEvent@覆盖公共布尔 onInterceptTouchEvent(MotionEvent ev) {返回 super.onInterceptTouchEvent(ev) &&mGestureDetector.onTouchEvent(ev);}}
XScrollDetector
在哪里
class XScrollDetector extends GestureDetector.SimpleOnGestureListener {@覆盖公共布尔 onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {返回 Math.abs(distanceY)
因此 ParentRecyclerView
要求子视图(在我们的例子中是 VerticalRecyclerView)来处理滚动事件.如果子视图处理,则父视图不执行其他操作,父视图最终会处理滚动.
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)
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:
Define CustomLinearLayoutManager
extending LinearLayoutManager
like this:
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public boolean canScrollVertically() {
return false;
}
}
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
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;
}
}
and set it as layoutManger
to the child RecyclerView
:
childRecyclerView = (RecyclerView)itemView.findViewById(R.id.child_rv);
childRecyclerView.setLayoutManager(new CustomGridLayoutManager(context, 3));
childRecyclerView.setAdapter(new ChildAdapter()); // some adapter
So basically parent RecyclerView
is only listening to horizontal scrolls and child RecyclerView
is only listening to vertical scrolls.
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);
}
}
Where XScrollDetector
is
class XScrollDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return Math.abs(distanceY) < Math.abs(distanceX);
}
}
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屋!