import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.webkit.WebView
import androidx.core.view.MotionEventCompat
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat
class NestedWebView(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
WebView(context!!, attrs, defStyleAttr), NestedScrollingChild {
private var mLastY = 0
private val mScrollOffset = IntArray(2)
private val mScrollConsumed = IntArray(2)
private var mNestedOffsetY = 0
private val mChildHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this)
constructor(context: Context?) : this(context, null) {}
constructor(context: Context?, attrs: AttributeSet?) : this(
context,
attrs,
R.attr.webViewStyle
) {
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
var returnValue = false
val event = MotionEvent.obtain(ev)
val action = MotionEventCompat.getActionMasked(event)
if (action == MotionEvent.ACTION_DOWN) {
mNestedOffsetY = 0
}
val eventY = event.y.toInt()
event.offsetLocation(0f, mNestedOffsetY.toFloat())
when (action) {
MotionEvent.ACTION_MOVE -> {
var totalScrollOffset = 0
var deltaY = mLastY - eventY
// NestedPreScroll
if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
totalScrollOffset += mScrollOffset[1]
deltaY -= mScrollConsumed[1]
event.offsetLocation(0f, (-mScrollOffset[1]).toFloat())
mNestedOffsetY += mScrollOffset[1]
}
returnValue = super.onTouchEvent(event)
// NestedScroll
if (dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) {
totalScrollOffset += mScrollOffset[1]
event.offsetLocation(0f, mScrollOffset[1].toFloat())
mNestedOffsetY += mScrollOffset[1]
mLastY -= mScrollOffset[1]
}
mLastY = eventY - totalScrollOffset
}
MotionEvent.ACTION_DOWN -> {
returnValue = super.onTouchEvent(event)
mLastY = eventY
// start NestedScroll
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
returnValue = super.onTouchEvent(event)
// end NestedScroll
stopNestedScroll()
}
}
return returnValue
}
// Nested Scroll implements
override fun setNestedScrollingEnabled(enabled: Boolean) {
mChildHelper.isNestedScrollingEnabled = enabled
}
override fun isNestedScrollingEnabled(): Boolean {
return mChildHelper.isNestedScrollingEnabled
}
override fun startNestedScroll(axes: Int): Boolean {
return mChildHelper.startNestedScroll(axes)
}
override fun stopNestedScroll() {
mChildHelper.stopNestedScroll()
}
override fun hasNestedScrollingParent(): Boolean {
return mChildHelper.hasNestedScrollingParent()
}
override fun dispatchNestedScroll(
dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int,
offsetInWindow: IntArray?
): Boolean {
return mChildHelper.dispatchNestedScroll(
dxConsumed,
dyConsumed,
dxUnconsumed,
dyUnconsumed,
offsetInWindow
)
}
override fun dispatchNestedPreScroll(
dx: Int,
dy: Int,
consumed: IntArray?,
offsetInWindow: IntArray?
): Boolean {
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
}
override fun dispatchNestedFling(
velocityX: Float,
velocityY: Float,
consumed: Boolean
): Boolean {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed)
}
override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY)
}
init {
isNestedScrollingEnabled = true
}
}
In your Layout:
<com.nestedscrollwebviewexample.NestedWebView
android:id="@+id/nested_webview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000000"
android:fillViewport="true"
android:focusable="true"
android:isScrollContainer="false"
android:visibility="visible"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />