How can I prevent diagonal swipe on Viewpager2, only allow to swipe if gesture is strictly horizontally.
3 Answers
This how make it work
source from Medium
fun ViewPager2.reduceDragSensitivity() {
val recyclerViewField = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
val recyclerView = recyclerViewField.get(this) as RecyclerView
val touchSlopField = RecyclerView::class.java.getDeclaredField("mTouchSlop")
touchSlopField.isAccessible = true
val touchSlop = touchSlopField.get(recyclerView) as Int
touchSlopField.set(recyclerView, touchSlop*3)
}
Also you must have Recyclerview like this
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layerType="hardware"
android:orientation="vertical"
android:overScrollMode="never"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerArtist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
android:layerType="hardware"
android:orientation="vertical"
android:overScrollMode="never" />
</androidx.core.widget.NestedScrollView>
also
ViewCompat.setNestedScrollingEnabled(recyclerView,false)

- 11
- 1
- 3
-
Putting recyclerview inside a NestedScrollView is really a bad idea since you are breaking the purpose of the recyclerview pattern by bypassing the fact that it will only load visible items by default. – Harshal Pudale Aug 25 '22 at 11:44
after few hour struggling with viewpager2, i realize the simple way is back to viewpager

- 11
- 1
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 04 '23 at 17:14
I found this awesome article that addresses this issue in depth. The problem is actually with the recyclerview which is the backbone of the new viewpager2.
Many times, even though an horizontal gesture is performed on a child RecyclerView, the parent RecyclerView kicks in and intercepts the touch event instead of the child RecyclerView, resulting in a small vertical scroll instead of an horizontal scroll. This actually happens when the scroll gesture is not perfectly horizontal. It’s actually diagonal, even if you can see that the vertical distance of the gesture is small compared to its horizontal distance and its intent was clearly horizontal
Further, the author of the article explains the cause of this behavior by digging into the recyclerview code
In summary, the problem is that when the RecyclerView is configured to scroll in a single direction as it’s usually the case, it doesn’t test if the global shape of the gesture is more horizontal (abs(dx) > abs(dy)) or vertical ( abs(dy) > abs(dx)) before deciding to intercept it, potentially conflicting with a child view scrolling in the opposite direction.
Here's the article link. Scroll to the bottom, you'll find the solution. I think this solution is better than modifying the touch slop value to reduce the drag sensitivity.

- 178
- 1
- 2
- 7