解决coordinatorlayout嵌套webView遇到的问题

来源:互联网 发布:人工智能动作电影 编辑:程序博客网 时间:2024/04/29 08:55

一、介绍
在符合material desin设计中,我们的内容详情页通常会需要webview实现NestedScrollingChild那样的功能,原生webview不支持,但是嵌套在NestedScrollView里面,我们加载网页内部的很多js功能都无法实现了,只能通过自定义webview实现NestedScrollingChild接口来实现。
国外的大神Tobias Rohloff 实现了该功能,在此谢谢他。
然而他的有太多bug,对这个进行一些更改:

二、具体实现

/** * Created by * mi on 2017/7/21. */public class NestedScrollWebView extends WebView implements NestedScrollingChild {    public static final String TAG = NestedScrollWebView.class.getSimpleName();    private int mLastMotionY;    private final int[] mScrollOffset = new int[2];    private final int[] mScrollConsumed = new int[2];    private int mNestedYOffset;    private NestedScrollingChildHelper mChildHelper;    public NestedScrollWebView(Context context) {        super(context);        init();    }    public NestedScrollWebView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public NestedScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private void init() {        mChildHelper = new NestedScrollingChildHelper(this);        setNestedScrollingEnabled(true);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        boolean result = false;        MotionEvent trackedEvent = MotionEvent.obtain(event);        final int action = MotionEventCompat.getActionMasked(event);        if (action == MotionEvent.ACTION_DOWN) {            mNestedYOffset = 0;        }        int y = (int) event.getY();        event.offsetLocation(0, mNestedYOffset);        switch (action) {            case MotionEvent.ACTION_DOWN:                mLastMotionY = y;                startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);                result = super.onTouchEvent(event);                break;            case MotionEvent.ACTION_MOVE:                int deltaY = mLastMotionY - y;                if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {                    deltaY -= mScrollConsumed[1];                    trackedEvent.offsetLocation(0, mScrollOffset[1]);                    mNestedYOffset += mScrollOffset[1];                }                int oldY = getScrollY();                mLastMotionY = y - mScrollOffset[1];                int newScrollY = Math.max(0, oldY + deltaY);                deltaY -= newScrollY - oldY;                if (dispatchNestedScroll(0, newScrollY - deltaY, 0, deltaY, mScrollOffset)) {                    mLastMotionY -= mScrollOffset[1];                    trackedEvent.offsetLocation(0, mScrollOffset[1]);                    mNestedYOffset += mScrollOffset[1];                }                if(mScrollConsumed[1]==0 && mScrollOffset[1]==0) {                    trackedEvent.recycle();                    result = super.onTouchEvent(trackedEvent);                }                break;            case MotionEvent.ACTION_POINTER_DOWN:            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                stopNestedScroll();                result = super.onTouchEvent(event);                break;        }        return result;    }    // 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 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);    }}

3、应用

  <com.kkeji.news.client.view.webview.NestedScrollWebView                app:layout_behavior="@string/appbar_scrolling_view_behavior"                android:id="@+id/content_WebView"                android:layout_width="match_parent"                android:layout_height="match_parent" />

四、一些要注意的问题:

实践发现,如果网页内部有a标签存在时
1、href属性不能为“#”,否则会返回顶部,在webview里面没有这个问题存在。
2、NestedScrollWebView要写在最外层才会生效,这关系到与coordinatorlayout之间的协调。