Android ScrollView从子WebView窃取触摸事件

时间:2019-01-17 12:47:11

标签: java android android-webview android-scrollview

我有一个布局,其中WebView位于ScrollView内,并且我希望能够在这两个之间切换,以确定哪个人接收了触摸事件。不幸的是,无论我做什么,ScrollView似乎都从WebView窃取了触摸事件,从而无法在WebView中平滑地平移和缩放。有解决方案吗?

我尝试过ScrollView.SetOnTouchListener();并设置了一个返回true的侦听器,这将阻止ScrollView滚动,但是并不能防止在触摸事件到达WebView之前被拦截。

我也尝试过WebView.Parent.RequestDisallowInterceptTouchEvent(true);WebView.Parent.RequestDisallowInterceptTouchEvent(true);,它们似乎都无效。

2 个答案:

答案 0 :(得分:1)

尝试使用NestedScrollView并将NestedScrollingChild实现到自定义WebView。

Reference Link

和一些代码

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) {
    this(context, null);
}

public NestedWebView(Context context, AttributeSet attrs) {
    this(context, attrs, android.R.attr.webViewStyle);
}

public NestedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    boolean returnValue = false;

    MotionEvent event = MotionEvent.obtain(ev);
    final int action = MotionEventCompat.getActionMasked(event);
    if (action == MotionEvent.ACTION_DOWN) {
        mNestedOffsetY = 0;
    }
    int eventY = (int) event.getY();
    event.offsetLocation(0, mNestedOffsetY);
    switch (action) {
        case MotionEvent.ACTION_MOVE:
            int deltaY = mLastY - eventY;
            // NestedPreScroll
            if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
                deltaY -= mScrollConsumed[1];
                mLastY = eventY - mScrollOffset[1];
                event.offsetLocation(0, -mScrollOffset[1]);
                mNestedOffsetY += mScrollOffset[1];
            }
            returnValue = super.onTouchEvent(event);

            // NestedScroll
            if (dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) {
                event.offsetLocation(0, mScrollOffset[1]);
                mNestedOffsetY += mScrollOffset[1];
                mLastY -= mScrollOffset[1];
            }
            break;
        case MotionEvent.ACTION_DOWN:
            returnValue = super.onTouchEvent(event);
            mLastY = eventY;
            // start NestedScroll
            startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            returnValue = super.onTouchEvent(event);
            // end NestedScroll
            stopNestedScroll();
            break;
    }
    return returnValue;
}

// Nested Scroll implements
@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);
}

}

声明NestedWebView而不是在NestedScrollView中声明WebView。例如

<com.nestedscrollwebviewexample.NestedWebView
    android:id="@+id/nested_webview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#000000"
    android:fillViewport="true"
    android:focusable="true"
    android:isScrollContainer="false"
    android:visibility="visible"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_scrollFlags="scroll|exitUntilCollapsed" />

除了声明Webview之外,您还可以在Activity中将其初始化为NestedWebView

 private NestedWebView mShopWebView;
    mShopWebView = (NestedWebView) findViewById(R.id.url_load_webview);

希望这可以达到目的。

答案 1 :(得分:0)

为此,我在屏幕上以与ScrollView相同的层次结构在屏幕上添加了一个浮动WebView,并将其位置链接到滚动值,然后使用WebView.BringToFront和ScrollView.BringToFront切换了触摸控制。