SwipeRefreshLayout未拦截NestedScrollingChild的MotionEvent

9
我正在使用一个NestedScrollWebView(受NestedScrollView的影响较大),它解决了在CoordinatorLayout中使用WebView时存在的多个已知问题问题
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="enterAlways|scroll|snap">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:titleTextAppearance="@style/TextAppearance.AppCompat.Subhead"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

            <ProgressBar
                android:id="@+id/progressBar"
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:layout_gravity="bottom"
                android:visibility="gone"
                style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>

        </FrameLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <com.example.app.widget.NestedScrollWebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>

NestedScrollWebView 可以很好地与 AppBarLayoutenterAlways|scroll|snap 滚动标志一起使用,但与 SwipeRefreshLayout 的兼容性不太好。


我从NestedScrollWebView中删除了以下行:

setOverScrollMode(WebView.OVER_SCROLL_NEVER);

这可以确保视图不会显示过度滚动指示器。我想要出现过度滚动指示器,但即使启用了过度滚动,也不应发生以下情况。
据我所知,SwipeRefreshLayout 应该拦截任何触摸事件,导致刷新指示器被拖动(基于其实现的 onInterceptTouchEvent())。SwipeRefreshLayout 还会拒绝对任何启用嵌套滚动的子项进行 requestDisallowInterceptTouchEvent();这对于 NestedScrollWebView 是正确的。因此,应以 以下方式 处理这些事件:

如果您从 onInterceptTouchEvent() 返回 true,则先前处理触摸事件的子视图将接收到 ACTION_CANCEL,并且从那时起,事件将发送到父类的 onTouchEvent() 方法进行常规处理。

相反,我看到的行为是 SwipeRefreshLayout 窃取了 NestedScrollWebView 的触摸事件,但它从未真正拦截它们。由于 NestedScrollWebView 从未收到 ACTION_CANCEL 触摸事件,并且即使 SwipeRefreshLayout 指示器被向下拖动,它仍然会接收后续事件,这一事实得以证明。

以下屏幕截图展示了这一点;其中显示了 SwipeRefreshLayout 指示器和 WebView 的过度滚动指示器同时显示。

overscroll and refresh indicator shown in tandem

我不能想出为什么会这样。正如我之前提到的,SwipeRefreshLayout 应该能够与启用嵌套滚动的任何视图良好地配合使用,但由于某种原因,在这种情况下它无法正常工作。可能的问题是什么?

更新

我认为这与NestedScrollWebView处理dispatchNestedPre...方法的方式有关,以及它总是将整个MotionEvent传递给super.onTouchEvent()方法。根据文档:

嵌套预滚动事件就像触摸拦截一样,是嵌套滚动事件的前置事件。dispatchNestedPreScroll为嵌套滚动操作中的父视图提供了一个机会,在子视图使用之前消耗部分或全部滚动操作。

现在我必须找出如何重新设计NestedScrollWebView以正确处理这些方法。


可能最简单的解决方案是将NestedScrollWebView替换为包装WebViewNestedScrollView - Stas Lelyuk
@StasLelyuk 我应该提到; 我之前放弃了那个实现,因为它不能正常工作。 WebView 可能会意外增长长度,并且某些功能(例如捏合缩放)无法与 NestedScrollView 一起使用。这些问题是 NestedScrollWebView 解决的,唯一的问题是它不能与 SwipeRefreshLayout 完美地配合使用。 - Bryan
有道理。如果您在问题中加入这些信息,将非常有帮助。 - Stas Lelyuk
我使用了你的代码并尝试使用swiper获取你的当前行为,但它似乎对我来说工作正常! - user6490462
@Ibrahim Ah,我忘了,我对NestedScrollWebView做了一个更改,我删除了这一行:setOverScrollMode(WebView.OVER_SCROLL_NEVER)。我想要过度滚动指示器,但在其他情况下(即使有过度滚动指示器),SwipeRefreshLayout也会拦截滚动手势,因此当滚动超过屏幕顶部时,过度滚动指示器不会出现。 - Bryan
1个回答

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接