Подтвердить что ты не робот

Исправлена ​​ошибка остановки NestedScrollView для Nougat (API 25)

У меня странная проблема с запуском NestedScrollView на Nexus 5x (7.1.2) и Google Pixel (7.1.1). В других версиях ОС он работает нормально.

Флинковая анимация иногда останавливается сразу после поднятия пальца. Он держится, а следующие несколько выстрелов также могут остановиться. Чтобы воспроизвести его, вам нужно бросить несколько раз вверх и вниз.

В журналах эти выбросы выглядят почти одинаково с точки зрения скорости, направления и т.д., поэтому я не могу найти настоящую причину этой ошибки.

Также NestedScrollView не обязательно должен находиться внутри CoordinatorLayout, он также может иметь не NestedScrollingChild вообще.

Например, эта ошибка воспроизводится с одним из следующих NestedScrollView детей:

1) LinearLayout, заполненном TextViews

2) WebView

3) LinearLayout, заполненном RecyclerViews.

Я знаю о возможных проблемах с RecyclerView и Behaviors внутри CoordinatorLayout, но это не связано. Поэтому, пожалуйста, не упоминайте никаких

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

или что-то в этом роде.

Пример кода:

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

Ответ 1

Значит, это ошибка в NestedScrollView. Я сделал обходной путь для этого, но все еще ожидаю, что исправление будет исправлено со стороны Google.

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

Edit

Похоже, проблема исправлена ​​в версии lib 26.0.0-beta2

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

Изменить 2: Хотя прокрутка работает отлично сейчас, в моем приложении я могу постоянно воспроизводить эту ошибку:

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

Если кто-то встретит это также, вы можете найти обходной путь в упомянутом потоке.

Ответ 2

в соответствии с Анимация руководства по стилю прокрутки, при переопределении computeScroll(), после использования mScroller.computeScrollOffset() для вычисления правильного смещения прокрутки, нам нужно использовать:

ViewCompat.postInvalidateOnAnimation(this);

для анимации следующего прокрутки. Однако в NestedScrollView computeScroll() выглядит так:

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

Он не запрашивает следующую анимацию прокрутки! Это означает, что после использования mScroller.fling(...) метод computeScroll() иногда будет вызван только один раз, а просмотр не будет выполняться.

Чтобы устранить эту проблему, я попытался заменить computeScroll таким образом:

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

Это может показаться неплохим решением, но сейчас оно отлично работает.

Последняя версия NestedScrollView добавила ViewCompat.postInvalidateOnAnimation(this).