Late to this question and I come up with a different approach to fix this issue by override
the WebView
onTouchEvent
method. It works on both ViewPager
and ViewPager2
. Hope this would help the future SO.
Note: Replace your WebView
with NestedScrollWebView
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.webkit.WebView
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat
class NestedScrollWebView : WebView, NestedScrollingChild {
companion object {
val TAG: String = NestedScrollWebView::class.java.simpleName
}
private var lastMotionX: Int = 0
private var lastMotionY: Int = 0
private val scrollOffset = IntArray(2)
private val scrollConsumed = IntArray(2)
private var nestedOffsetY: Int = 0
private var childHelper = NestedScrollingChildHelper(this)
constructor(context: Context) : super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
isNestedScrollingEnabled = true
}
override fun onTouchEvent(event: MotionEvent): Boolean {
var result = false
val trackedEvent = MotionEvent.obtain(event)
val action = event.actionMasked
if (action == MotionEvent.ACTION_DOWN) {
nestedOffsetY = 0
}
val x = event.x.toInt()
val y = event.y.toInt()
event.offsetLocation(0f, nestedOffsetY.toFloat())
when (action) {
MotionEvent.ACTION_DOWN -> {
lastMotionX = x
lastMotionY = y
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
result = super.onTouchEvent(event)
}
MotionEvent.ACTION_MOVE -> {
var deltaY = lastMotionY - y
if (kotlin.math.abs(deltaY) > kotlin.math.abs(lastMotionX - x) &&
(canScrollVertically(1) || canScrollVertically(-1))
) {
requestDisallowInterceptTouchEvent(true)
}
if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
deltaY -= scrollConsumed[1]
trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat())
nestedOffsetY += scrollOffset[1]
}
lastMotionY = y - scrollOffset[1]
val oldY = scrollY
val newScrollY = Math.max(0, oldY + deltaY)
val dyConsumed = newScrollY - oldY
val dyUnconsumed = deltaY - dyConsumed
if (dispatchNestedScroll(0, dyConsumed, 0, dyUnconsumed, scrollOffset)) {
lastMotionY -= scrollOffset[1]
trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat())
nestedOffsetY += scrollOffset[1]
}
result = super.onTouchEvent(trackedEvent)
trackedEvent.recycle()
}
MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
stopNestedScroll()
requestDisallowInterceptTouchEvent(false)
result = super.onTouchEvent(event)
}
}
return result
}
// NestedScrollingChild
override fun setNestedScrollingEnabled(enabled: Boolean) {
childHelper.isNestedScrollingEnabled = enabled
}
override fun stopNestedScroll() {
childHelper.stopNestedScroll()
}
override fun isNestedScrollingEnabled() =
childHelper.isNestedScrollingEnabled
override fun startNestedScroll(axes: Int) =
childHelper.startNestedScroll(axes)
override fun hasNestedScrollingParent() =
childHelper.hasNestedScrollingParent()
override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?) =
childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?) =
childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean) =
childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float) =
childHelper.dispatchNestedPreFling(velocityX, velocityY)
}