0

How can I prevent diagonal swipe on Viewpager2, only allow to swipe if gesture is strictly horizontally.

I dot not want this

I want this

3 Answers3

1

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)
  • 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
1

after few hour struggling with viewpager2, i realize the simple way is back to viewpager

zer0
  • 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
0

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.

Harshal Pudale
  • 178
  • 1
  • 2
  • 7