Skip to content

Instantly share code, notes, and snippets.

@Mygod
Created March 12, 2020 20:02
Show Gist options
  • Save Mygod/65dae294c75b6c36133d4ae7c08a662c to your computer and use it in GitHub Desktop.
Save Mygod/65dae294c75b6c36133d4ae7c08a662c to your computer and use it in GitHub Desktop.
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.webkit.WebView
import androidx.customview.widget.ViewDragHelper
class NestedScrollingWebView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null) : WebView(context, attrs) {
companion object {
private val TAG = "NestedScrollingWebView"
}
private var isBeingDragged = false
private var activePointerId = ViewDragHelper.INVALID_POINTER
private var lastMotionX = 0f
private var lastMotionY = 0f
private var nestedXOffset = 0f
private var nestedYOffset = 0f
// object-local variables for receiving output, hurray for JVM
private val scrollConsumed = IntArray(2)
init {
// ...because why else would you be using this widget?
isNestedScrollingEnabled = true
}
override fun overScrollBy(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int,
scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int,
isTouchEvent: Boolean): Boolean {
// Log.d("TRACKME", "$deltaX, $deltaY, $scrollX, $scrollY, $scrollRangeX, $scrollRangeY, $maxOverScrollX, $maxOverScrollY, $isTouchEvent")
return dispatchNestedScroll(0, 0, deltaX, deltaY, null) || super.overScrollBy(
deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent)
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
when (ev.actionMasked) {
MotionEvent.ACTION_DOWN -> {
parent?.requestDisallowInterceptTouchEvent(true)
activePointerId = ev.getPointerId(0)
isBeingDragged = true
lastMotionX = ev.x
lastMotionY = ev.y
nestedXOffset = 0f
nestedYOffset = 0f
startNestedScroll(View.SCROLL_AXIS_VERTICAL)
}
MotionEvent.ACTION_MOVE -> if (isBeingDragged) {
val activePointerIndex = ev.findPointerIndex(activePointerId)
if (activePointerIndex == -1) {
Log.e(TAG, "Invalid pointerId=$activePointerId in onInterceptTouchEvent")
} else {
parent?.requestDisallowInterceptTouchEvent(true)
val x = ev.getX(activePointerIndex)
val y = ev.getY(activePointerIndex)
if (dispatchNestedPreScroll((lastMotionX - x).toInt(), (lastMotionY - y).toInt(), scrollConsumed, null)) {
// Log.d(TAG, "nested ${scrollConsumed.joinToString()}, $nestedYOffset")
nestedXOffset += scrollConsumed[0]
nestedYOffset += scrollConsumed[1]
}
lastMotionX = x
lastMotionY = y
// dispatchNestedScroll will later be called by overScrollBy, as a result of super.onTouchEvent
}
}
MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
activePointerId = ViewDragHelper.INVALID_POINTER
isBeingDragged = false
stopNestedScroll()
nestedXOffset = 0f
nestedYOffset = 0f
}
}
val vtev = MotionEvent.obtain(ev)
vtev.offsetLocation(nestedXOffset, nestedYOffset)
super.onTouchEvent(vtev)
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment