Dimezis
Dimezis

Reputation: 1595

NestedScrollView fling stopping bug on Nougat (API 25)

I have a strange issue with NestedScrollView fling on Nexus 5x (7.1.2) and Google Pixel (7.1.1). On other OS versions it works OK.

Fling animation sometimes stops right after lifting up a finger. It stucks and the next few flings may be stopping as well. In order to reproduce it, you need to fling several times up and down.

In logs these flings look pretty much the same in terms of velocity, direction, etc, so I can't find a real cause of this bug.

Also NestedScrollView doesn't necessarily need to be inside of CoordinatorLayout, it also can have no NestedScrollingChild at all.

For example, this bug is reproducible with one of the following NestedScrollView children:

1) LinearLayout populated with TextViews

2) WebView

3) LinearLayout populated with RecyclerViews.

I know about possible issues with RecyclerView and Behaviours inside of CoordinatorLayout, but it's not related. So please don't mention any

recyclerView.getLayoutManager().setAutoMeasureEnabled(true);
recyclerView.setNestedScrollingEnabled(false);

or things like that.

Code sample:

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:text="Put a super long text here"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:text="Put a super long text here"/>

    </LinearLayout>

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

Upvotes: 18

Views: 2669

Answers (2)

Xiang Zhang
Xiang Zhang

Reputation: 43

according to Animating a Scroll Gesture training guide, while overriding computeScroll(), after using mScroller.computeScrollOffset() to calculate proper offset to scroll view, we need use:

ViewCompat.postInvalidateOnAnimation(this);

to animate next scroll. However, in the NestedScrollView, the computeScroll() looks like this:

public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
    ...     
    }
}

It doesn't request next scroll animation! Which means that after using mScroller.fling(...), the computeScroll() method will sometimes only get called one time, and view doesn't keep fling.

To fix this problem, I have tried to replace the computeScroll in this way:

public void computeScroll(){
    if(mScroller.computeScrollOffset()){
       ...
       ViewCompat.postInvalidateOnAnimation(this); 
    }
}

It may not sound a good solution, but it just works fine for now.

Recent version of NestedScrollView has added the ViewCompat.postInvalidateOnAnimation(this).

Upvotes: 0

Dimezis
Dimezis

Reputation: 1595

So it's clearly a bug in NestedScrollView. I have made a workaround for this, but still waiting for a proper fix from Google side.

https://github.com/Dimezis/FlingableNestedScrollView/

Edit:

Looks like the issue is fixed in support lib 26.0.0-beta2

https://chris.banes.me/2017/06/09/carry-on-scrolling/

Edit 2: Although the scrolling works fine now, in my app I can constantly reproduce this bug:

https://issuetracker.google.com/issues/37051723

If someone encounters it as well, you can find a workaround in a thread mentioned.

Upvotes: 7

Related Questions