SwipeRefreshLayout is not intercepting the MotionEvent of the NestedScrollingChild
Asked Answered
D

1

9

I am using a NestedScrollWebView (heavily influenced by the NestedScrollView), which solves many of the known issues associated with using a WebView in a CoordinatorLayout.

<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>

The NestedScrollWebView works great with the AppBarLayout and the enterAlways|scroll|snap scroll flags, but not so well with the SwipeRefreshLayout.


I removed the following line from the NestedScrollWebView:

setOverScrollMode(WebView.OVER_SCROLL_NEVER);

Which makes sure the view does not display over scroll indicators. I want over scroll indicators to appear, but the following circumstances should not occur even with over scroll enabled.


From what I understand the SwipeRefreshLayout should intercept any touch event that causes the refresh indicator to be dragged (based on its implementation of onInterceptTouchEvent()). SwipeRefreshLayout also denies any requestDisallowInterceptTouchEvent() to any child that has nested scrolling enabled; which is true for the NestedScrollWebView. Therefore, these events should be handled in the following manner:

If you return true from onInterceptTouchEvent(), the child view that was previously handling touch events receives an ACTION_CANCEL, and the events from that point forward are sent to the parent's onTouchEvent() method for the usual handling.

Instead, the behavior I see is that the SwipeRefreshLayout does spy on the touch events of the NestedScrollWebView but it never actually intercepts them. As evidenced by the fact that the NestedScrollWebView never receives an ACTION_CANCEL touch event, and it continues to receive subsequent events even though the SwipeRefreshLayout indicator is being dragged down.

This is demonstrated in the following screenshot; which shows the indicator of the SwipeRefreshLayout as well as the over scroll indicator of the WebView being displayed at the same time.

overscroll and refresh indicator shown in tandem

I cannot figure out why this would be the case. As I mentioned previously, the SwipeRefreshLayout should work well with any view that has nested scrolling enabled, but for some reason it does not work in this case. What could be the issue?


Update

I think it has something to do with the way the NestedScrollWebView handles dispatchNestedPre... methods and the fact that it always passes the entire MotionEvent to the super.onTouchEvent() method. According to the documentation:

Nested pre-scroll events are to nested scroll events what touch intercept is to touch. dispatchNestedPreScroll offers an opportunity for the parent view in a nested scrolling operation to consume some or all of the scroll operation before the child view consumes it.

Now I have to figure out how to rework the NestedScrollWebView to handle these methods properly.

Dree answered 18/8, 2017 at 16:44 Comment(5)
Probably the most simplest solution is replace NestedScrollWebView with NestedScrollView which wraps WebView.Nogging
@StasLelyuk I should have mentioned; I moved away from that implementation in the first place because it does not work correctly. The WebView can grow in length unexpectedly, and certain features (such as pinch to zoom) do not work along with the NestedScrollView. These issues are what the NestedScrollWebView solves, the only issue is that it does not work perfectly with the SwipeRefreshLayout.Dree
That's make sense. Would be pretty helpful if you put this info into your question as well.Nogging
I used your code and tried to get your current behaviors with swiper, but it's seems work fine with me!Warily
@Ibrahim Ah, I forgot, I did make one change to the NestedScrollWebView, I removed this line: setOverScrollMode(WebView.OVER_SCROLL_NEVER). I want over scroll indicators, but in other instances (even with over scroll indicators) the SwipeRefreshLayout intercepts the scroll gesture, so the over scroll indicator doesn't appear when scrolled past the top of the screen.Dree
K
0

Hope you will get some solution from new released interfaces:

NestedScrollingChild interfaces:

NestedScrollingParent interfaces:

Thank you.

Kenner answered 15/2, 2019 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.