Java tutorial
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.focus.webkit; import android.content.Context; 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.webkit.WebView; /** * WebView that supports nested scrolls (for using in a CoordinatorLayout). * * Based on: * https://github.com/takahirom/webview-in-coordinatorlayout */ public class NestedWebView extends WebView implements NestedScrollingChild { private int mLastY; private final int[] mScrollOffset = new int[2]; private final int[] mScrollConsumed = new int[2]; private int mNestedOffsetY; private NestedScrollingChildHelper mChildHelper; public NestedWebView(Context context, AttributeSet attrs) { super(context, attrs); mChildHelper = new NestedScrollingChildHelper(this); setNestedScrollingEnabled(true); } @Override public boolean onTouchEvent(MotionEvent ev) { boolean eventHandled = false; final MotionEvent event = MotionEvent.obtain(ev); final int action = MotionEventCompat.getActionMasked(event); if (action == MotionEvent.ACTION_DOWN) { mNestedOffsetY = 0; } final int eventY = (int) event.getY(); event.offsetLocation(0, mNestedOffsetY); switch (action) { case MotionEvent.ACTION_MOVE: int deltaY = mLastY - eventY; if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { deltaY -= mScrollConsumed[1]; mLastY = eventY - mScrollOffset[1]; event.offsetLocation(0, -mScrollOffset[1]); mNestedOffsetY += mScrollOffset[1]; } eventHandled = super.onTouchEvent(event); if (dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) { event.offsetLocation(0, mScrollOffset[1]); mNestedOffsetY += mScrollOffset[1]; mLastY -= mScrollOffset[1]; } break; case MotionEvent.ACTION_DOWN: eventHandled = super.onTouchEvent(event); mLastY = eventY; startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: eventHandled = super.onTouchEvent(event); stopNestedScroll(); break; default: // We don't care about other touch events } return eventHandled; } @Override public void setNestedScrollingEnabled(boolean enabled) { mChildHelper.setNestedScrollingEnabled(enabled); } @Override public boolean isNestedScrollingEnabled() { return mChildHelper.isNestedScrollingEnabled(); } @Override public boolean startNestedScroll(int axes) { return mChildHelper.startNestedScroll(axes); } @Override public void stopNestedScroll() { mChildHelper.stopNestedScroll(); } @Override public boolean hasNestedScrollingParent() { return mChildHelper.hasNestedScrollingParent(); } @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); } @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); } }