package com.pitchedapps.frost.views import android.annotation.SuppressLint import android.content.Context import android.graphics.Bitmap import android.support.v4.view.MotionEventCompat import android.support.v4.view.NestedScrollingChild import android.support.v4.view.NestedScrollingChildHelper import android.support.v4.view.ViewCompat import android.util.AttributeSet import android.view.MotionEvent import android.view.View import android.webkit.WebResourceError import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient import com.pitchedapps.frost.utils.L import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject enum class WebStatus { LOADING, LOADED, ERROR } /** * Created by Allan Wang on 2017-05-29. * * Courtesy of takahirom * * https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java */ class FrostWebView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : WebView(context, attrs, defStyleAttr), NestedScrollingChild { private val childHelper = NestedScrollingChildHelper(this) private var lastY: Int = 0 private val scrollOffset = IntArray(2) private val scrollConsumed = IntArray(2) private var nestedOffsetY: Int = 0 val observable: Subject init { isNestedScrollingEnabled = true observable = BehaviorSubject.create() setupWebview() } @SuppressLint("SetJavaScriptEnabled") fun setupWebview() { settings.javaScriptEnabled = true setLayerType(View.LAYER_TYPE_HARDWARE, null) setWebViewClient(object : WebViewClient() { override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { super.onReceivedError(view, request, error) observable.onNext(WebStatus.ERROR) L.e("Error ${request}") } override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) observable.onNext(WebStatus.LOADING) } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) observable.onNext(WebStatus.LOADED) // CookieManager.getInstance().flush() } }) } override fun onTouchEvent(ev: MotionEvent): Boolean { val event = MotionEvent.obtain(ev) val action = MotionEventCompat.getActionMasked(event) if (action == MotionEvent.ACTION_DOWN) nestedOffsetY = 0 val eventY = event.y.toInt() event.offsetLocation(0f, nestedOffsetY.toFloat()) val returnValue: Boolean when (action) { MotionEvent.ACTION_MOVE -> { var deltaY = lastY - eventY // NestedPreScroll if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) { deltaY -= scrollConsumed[1] event.offsetLocation(0f, -scrollOffset[1].toFloat()) nestedOffsetY += scrollOffset[1] } lastY = eventY - scrollOffset[1] returnValue = super.onTouchEvent(event) // NestedScroll if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) { event.offsetLocation(0f, scrollOffset[1].toFloat()) nestedOffsetY += scrollOffset[1] lastY -= scrollOffset[1] } } MotionEvent.ACTION_DOWN -> { returnValue = super.onTouchEvent(event) lastY = eventY startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL) } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { returnValue = super.onTouchEvent(event) stopNestedScroll() } else -> return false } return returnValue } // Nested Scroll implements override fun setNestedScrollingEnabled(enabled: Boolean) { childHelper.isNestedScrollingEnabled = enabled } override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes) override fun stopNestedScroll() = childHelper.stopNestedScroll() 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) }