在项目中想使用一个和协调者布局联动使用的webview,发现sdk并没有提供这样的一个WebView,所以就只能自己手动继承webview并实现NestedScrollingChild2 接口,这样才能有效使用协调者布局 import android.content.Context; import android.support.v4.view.NestedScrollingChild2; import android.support.v4.view.NestedScrollingChildHelper; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.webkit.WebView; import android.widget.OverScroller; /** * * 实现 NestedScrollingChild2 可与协调者布局配合使用 * @author qjs */ public class NestedScrollWebView extends WebView implements NestedScrollingChild2 { private static final String TAG = NestedScrollWebView.class.getSimpleName(); private final int[] mScrollConsumed = new int[2]; private final int[] mScrollOffset = new int[2]; private int mLastMotionY; private VelocityTracker mVelocityTracker; private int mMinimumVelocity; private int mMaximumVelocity; private OverScroller mScroller; private int mLastScrollerY; private final NestedScrollingChildHelper mChildHelper; public NestedScrollWebView(Context context) { this(context, null); } public NestedScrollWebView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public NestedScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mChildHelper = new NestedScrollingChildHelper(this); setNestedScrollingEnabled(true); mScroller = new OverScroller(getContext()); final ViewConfiguration configuration = ViewConfiguration.get(getContext()); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); } private void initVelocityTrackerIfNotExists() { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } } private void recycleVelocityTracker() { if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } } public void fling(int velocityY) { startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); mScroller.fling(getScrollX(), getScrollY(), // start 0, velocityY, // velocities 0, 0, // x Integer.MIN_VALUE, Integer.MAX_VALUE, // y 0, 0); // overscroll mLastScrollerY = getScrollY(); ViewCompat.postInvalidateOnAnimation(this); } @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { final int x = mScroller.getCurrX(); final int y = mScroller.getCurrY(); int dy = y - mLastScrollerY; if (dy != 0) { int scrollY = getScrollY(); int dyUnConsumed = 0; int consumedY = dy; if (scrollY == 0) { dyUnConsumed = dy; consumedY = 0; } else if (scrollY + dy < 0) { dyUnConsumed = dy + scrollY; consumedY = -scrollY; } if (!dispatchNestedScroll(0, consumedY, 0, dyUnConsumed, null, ViewCompat.TYPE_NON_TOUCH)) { } } // Finally update the scroll positions and post an invalidation mLastScrollerY = y; ViewCompat.postInvalidateOnAnimation(this); } else { // We can't scroll any more, so stop any indirect scrolling if (hasNestedScrollingParent(ViewCompat.TYPE_NON_TOUCH)) { stopNestedScroll(ViewCompat.TYPE_NON_TOUCH); } // and reset the scroller y mLastScrollerY = 0; } } @Override public boolean onTouchEvent(MotionEvent event) { initVelocityTrackerIfNotExists(); MotionEvent vtev = MotionEvent.obtain(event); final int actionMasked = event.getAction(); switch (actionMasked) { case MotionEvent.ACTION_DOWN: mLastMotionY = (int) event.getRawY(); startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); mVelocityTracker.addMovement(vtev); mScroller.computeScrollOffset(); if (!mScroller.isFinished()) { mScroller.abortAnimation(); } break; case MotionEvent.ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getYVelocity(); if (Math.abs(initialVelocity) > mMinimumVelocity) { fling(-initialVelocity); } case MotionEvent.ACTION_CANCEL: stopNestedScroll(); recycleVelocityTracker(); break; case MotionEvent.ACTION_MOVE: final int y = (int) event.getRawY(); int deltaY = mLastMotionY - y; if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { vtev.offsetLocation(0, mScrollConsumed[1]); } mLastMotionY = y; int scrollY = getScrollY(); int dyUnconsumed = 0; if (scrollY == 0) { dyUnconsumed = deltaY; } else if (scrollY + deltaY < 0) { dyUnconsumed = deltaY + scrollY; vtev.offsetLocation(0, -dyUnconsumed); } mVelocityTracker.addMovement(vtev); boolean result = super.onTouchEvent(vtev); if (dispatchNestedScroll(0, deltaY - dyUnconsumed, 0, dyUnconsumed, mScrollOffset)) { } return result; default: break; } return super.onTouchEvent(vtev); } // NestedScrollingChild @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 boolean startNestedScroll(int axes, int type) { return mChildHelper.startNestedScroll(axes, type); } @Override public void stopNestedScroll() { mChildHelper.stopNestedScroll(); } @Override public void stopNestedScroll(int type) { mChildHelper.stopNestedScroll(type); } @Override public boolean hasNestedScrollingParent() { return mChildHelper.hasNestedScrollingParent(); } @Override public boolean hasNestedScrollingParent(int type) { return mChildHelper.hasNestedScrollingParent(type); } @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 dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow, int type) { return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type); } @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow, int type) { return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type); } @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); } }
WebView 实现 NestedScrollingChild2 可与协调者布局配合使用
最新推荐文章于 2024-05-15 00:48:43 发布