Android 当子recyclerview滚动到最后一项时禁用ViewPager分页
我有一个viewpager,在其中一个片段中,我有两个单独的片段,分别包含一个垂直和一个水平的recyclerview 当我将水平循环视图滚动到最后一项并尝试进一步滑动时,viewpager将滚动到下一页。我不希望这种情况发生。当我试图覆盖水平循环视图时,我想禁用viewpager的分页 但是,当我在其他地方滑动时,我不想禁用viewpager的分页。例如,如果我要滑动垂直recyclerview或父片段中的任何空白,它仍然会导致viewpager更改页面 我读过,如何禁用viewpager的分页。还有一个类似的地方是有一个子viewpager,但是我还没有成功地尝试用一个水平的recyclerview复制它 以下是一些结构: 允许我禁用分页的自定义viewpager(从上面的第一个SO链接获取): 对于水平循环视图,我设置了一个ontouchlistener(类似于上面的第二个SO链接): 额外观察:我注意到,有时如果在刷卡之前长按水平循环视图,它将不会进入viewpager的下一页。但是,如果我快速滑动,viewpager将转到下一页 有人知道这样做的正确方法吗 感谢您的帮助。这是解决方案Android 当子recyclerview滚动到最后一项时禁用ViewPager分页,android,android-fragments,android-viewpager,android-recyclerview,Android,Android Fragments,Android Viewpager,Android Recyclerview,我有一个viewpager,在其中一个片段中,我有两个单独的片段,分别包含一个垂直和一个水平的recyclerview 当我将水平循环视图滚动到最后一项并尝试进一步滑动时,viewpager将滚动到下一页。我不希望这种情况发生。当我试图覆盖水平循环视图时,我想禁用viewpager的分页 但是,当我在其他地方滑动时,我不想禁用viewpager的分页。例如,如果我要滑动垂直recyclerview或父片段中的任何空白,它仍然会导致viewpager更改页面 我读过,如何禁用viewpager的分
requestDisallowInterceptTouchEvent()
此方法不允许父对象移动。它会停止viewpager触摸事件
horizontalRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
rv.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
为了处理垂直滚动不再工作的问题,我改为: 为RecyclerView项目创建触摸侦听器
mGestureDetector = new GestureDetector(itemView.getContext(), new GestureListener());
/**
* Prevents the view pager from switching tabs when scrolling the carousel
*/
private class TouchListener implements RecyclerView.OnItemTouchListener {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
}
并实现一个手势监听器,当检测到水平滚动时,该监听器不允许触摸事件:
private class GestureListener extends SimpleOnGestureListener {
private final int Y_BUFFER = 10;
@Override
public boolean onDown(MotionEvent e) {
// Prevent ViewPager from intercepting touch events as soon as a DOWN is detected.
// If we don't do this the next MOVE event may trigger the ViewPager to switch
// tabs before this view can intercept the event.
mRecyclerView.requestDisallowInterceptTouchEvent(true);
return super.onDown(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (Math.abs(distanceX) > Math.abs(distanceY)) {
// Detected a horizontal scroll, prevent the viewpager from switching tabs
mRecyclerView.requestDisallowInterceptTouchEvent(true);
} else if (Math.abs(distanceY) > Y_BUFFER) {
// Detected a vertical scroll of large enough magnitude so allow the the event
// to propagate to ancestor views to allow vertical scrolling. Without the buffer
// a tab swipe would be triggered while holding finger still while glow effect was
// visible.
mRecyclerView.requestDisallowInterceptTouchEvent(false);
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
以防有人和我有同样的问题 如果层次结构中有一个
SwipeRefreshLayout
,并且它的子级确实为ViewCompat.isNestedScrollEnabled()
(在我的例子中是FrameLayout
),这将不起作用,因为在它传递RequestDisallowerWinterCeptTouchEvent()
之前签入了SwipeRefreshLayout
我花了一点时间调试,但下面是来自SwipeRefreshLayout
的具体检查:
if ((VERSION.SDK_INT >= 21 || !(this.mTarget instanceof AbsListView)) && (this.mTarget == null || ViewCompat.isNestedScrollingEnabled(this.mTarget))) {
super.requestDisallowInterceptTouchEvent(b);
}
通过删除
FrameLayout
,将SwipeRefreshLayout
的子对象设置为NestedScrollView
,我可以让Shabbir Dhangot的答案生效。对于kotlin,您可以尝试此解决方案
horizontalRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
val action = e.action
when (action) {
MotionEvent.ACTION_MOVE -> rv.parent.requestDisallowInterceptTouchEvent(true)
}
return false
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
找到任何解决方案。我正在寻找同样的问题。任何解决方法,请帮助。提前谢谢!这一个工作正常,但recyclerview滚动到最后一项。应该显示第一项。我必须使用请求。。。对于所有事件,都要真正防止这种行为。公共布尔值onInterceptTouchEvent(RecyclerView rv,MotionEvent e){rv.getParent().RequestDisallowWinterceptTouchEvent(true);返回false;}其工作状态。。但触摸horizontalRecyclerView时垂直滚动不起作用。有没有解决此问题的方法?不阻止垂直滚动添加:布尔值isVerticalScroll=Math.abs(dy)>Math.abs(dx);如果(!isVerticalScroll){rv.getParent().RequestDisallowWinterCeptTouchEvent(true)}。如何获取dy和dx的逻辑可以在RecyclerView源代码中找到。
if ((VERSION.SDK_INT >= 21 || !(this.mTarget instanceof AbsListView)) && (this.mTarget == null || ViewCompat.isNestedScrollingEnabled(this.mTarget))) {
super.requestDisallowInterceptTouchEvent(b);
}
horizontalRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
val action = e.action
when (action) {
MotionEvent.ACTION_MOVE -> rv.parent.requestDisallowInterceptTouchEvent(true)
}
return false
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})