I have a horizontal RecyclerView inside a Complex hierarchy that looks like this -
<ViewPager id="+@id/first">
<ViewPager id="+@id/second"> this viewpager is taking away the scroll event
<SwipeToRefreshLayout>
<RecyclerView> //this one is vertical
<RecyclerView id="@id/rv1"> //this one is horizontal
<RecyclerView id="@id/rv2"> //this one is working fine (different type)
</RecyclerView>
</SwipeToRefreshLayout>
</ViewPager>
</ViewPager>
Now the problem is that the second ViewPager is hijacking the scroll from Horizontal RV. There are 2 type of Horizontal RV (RV1 and RV2) in that vertical RV. But only one of them (RV1) is facing this problem. The second one (RV2) is working properly. Also when I press and hold then the scrolling is working fine. And when RV1 is already scrolling and has not settle, then also scrolling works fine. I have referred to other answers talking about setting nestedScrolling false. Nothing seems to be working.
Otherwise, they won’t scroll horizontally; the swipe is taken by the rootRecyclerView and so the you would see vertical movement.
I implemented one of them is a horizontal ViewPager2 and another one is implemented with horizontal RecyclerView (say, childRecyclerView ). The rootRecyclerView swipes vertically whereas the viewPager2 and childRecyclerView swipes horizontally.
I have a RecyclerView (say, rootRecyclerView) that can have different kinds of rows depending on some API response. I implemented one of them is a horizontal ViewPager2 and another one is implemented with horizontal RecyclerView (say, childRecyclerView ).
The Recyclerview also has another function to find out if you're in the last item in a very simple way using the canScrollHorizontally or canScrollVertically functions. So we basically tell the program to disallow scrolling on the parent (the Viewpager) when we haven’t reached the last item.
You can achieve this by overriding onInterceptTouchEvent method:
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
rv.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
@Override
public void onTouchEvent(@NonNull RecyclerView view, @NonNull MotionEvent event) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
This answer is Kotlin version of @Astril Veliu's answer
yourRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(view: RecyclerView, event: MotionEvent) {}
override fun onInterceptTouchEvent(view: RecyclerView, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
yourRecyclerView.parent?.requestDisallowInterceptTouchEvent(true)
}
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With