I have a ViewPager2 with a fragment inside,
in the fragment, I have a custom view with certain touch logic that involves moving the finger.
how do I prevent the ViewPager from swiping while the inner view intercepts the touch event?
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN || event?.action == MotionEvent.ACTION_MOVE) {
//Do some stuff here
}
return true
}
while swiping this view the view pager still swipes to other pages.
You can easily do that by creating a custom class inherits from viewPager and override two methods: “onTouchEvent()” and “onInterceptTouchEvent()” and return true or false to disable and enable the swiping on certain touch events i.e say swiping. // Detects the direction of swipe. Right or left.
You can react to touch events in your custom views and your activities. Android supports multiple pointers, e.g. fingers which are interacting with the screen. The base class for touch support is the MotionEvent class which is passed to Views via the onTouchEvent() method. you override the onTouchEvent() method.
"Touch slop" refers to the distance in pixels a user's touch can wander before the gesture is interpreted as scrolling.
Views can intercept the event by overriding onInterceptTouchEvent() . If onInterceptTouchEvent() returns true , it means the event was consumed and won't be passed onto descendent views. If it returns false , it means the view acknowledged the event but continued passing it down.
Set OnTouchListener for inner view. In onTouch()
method, call:
viewPager.requestDisallowInterceptTouchEvent(true)
ViewPager handles its swiping motion in onInterceptTouchEvent()
. Above code prevents ViewPager from calling onInterceptTouchEvent()
. When you're swiping, ViewPager returns true in onInterceptTouchEvent()
which also prevents touch events to be passed to child views. Therefore disallowing intercept allows child views to handle touch events.
Set back to false
when the inner view is not being touched.
From my experience, onInterceptTouchEvent()
prevents onTouchEvent()
. It does not prevent OnTouchListener
. So the key here is to set up OnTouchListener
for the inner view.
To fix this, you should extend the ViewPager2 like this:
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 * 6) // "6" was obtained experimentally
}
and call reduceDragSensitivity. So the viewpager2 will look like this:
view_pager.reduceDragSensitivity()
Example: https://github.com/ali-sardari/ViewPager2Example
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