Как получить процент прокрутки в NestedScrollView в любое время (плавно)?

Я хочу изменить альфа базы панели инструментов при прокрутке, как показано ниже:

введите описание изображения здесь

Сначала панель инструментов прозрачная, и при прокрутке вниз она будет все более и более видна, а в конце станет полностью непрозрачной (видимой).

Структура моего макета:

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_collapseMode="parallax">

            ....

        </RelativeLayout>

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

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

    <android.support.v4.widget.NestedScrollView
    android:id="@+id/scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

         ....

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

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

Содержимое вложенного прокрутки будет динамически меняться с сервера, поэтому я не знаю его высоты.

Я только что нашел 2 способа обнаружения scrollY:

  1. addOnScrollChangedListener:

    scroll.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
     @Override
     public void onScrollChanged() {
        // use scroll.getScrollY()     
    }
    });
    
  2. setOnScrollChangeListener:

    scroller.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
    
    @Override
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
    
    }
    });
    

Но ни один из этих путей не является гладким. например, если вы проверите значение scrollY (используя log.d()), вы увидите что-то вроде:

scrollY: 58
scrollY: 117
scrollY: 167
scrollY: 192
scrollY: 195
scrollY: 238
scrollY: 281
scrollY: 338 

Между цифрами большой разрыв.

Мой вопрос: как получить процент прокрутки каждый момент (плавно)? Или любой другой способ изменить альфа базы панели инструментов в текущей позиции прокрутки?


person Hamed Ghadirian    schedule 30.10.2016    source источник


Ответы (3)


Вы можете добавить scrollListener в ScrollView.

Расчет процента прокрутки вашего scrollView:

double percent = ((((float) scrollY) / ((float) (scrollContentHeight - screenHeight + statusBarHeight))));

введите описание изображения здесь


  • Верхний край отображаемой части вашего вида: scrollY = scrollView.getScrollY()

  • У scrollView есть один дочерний элемент, а scrollContentHeight = scrollView.getChildAt(0).getHeight() — это высота содержимого scrollView.

  • Нам нужно рассчитать максимальную высоту верхнего края в состоянии полной прокрутки: scrollContentHeight - screenHeight + statusBarHeight

  • Законченный! percent = scrollY*100 / (scrollContentHeight - screenHeight + statusBarHeight)

  • И установите цвет: view.setBackgroundColor(Color.argb((int) (255.0 * (percent/100)), r, g, b));


scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            int scrollY = scrollView.getScrollY();
            int scrollContentHeight = scrollView.getChildAt(0).getHeight();
            int screenHeight = Utility.getScreenHeight(context);
            int statusBarHeight = Utility.getStatusBarHeight(context);

            int color = getResources().getColor(R.color.colorPrimary);
            int r = (color >> 16) & 0xFF;
            int g = (color >> 8) & 0xFF;
            int b = (color >> 0) & 0xFF;

            double percent = ((((float) scrollY) / ((float) (scrollContentHeight - screenHeight + statusBarHeight))));
            if (percent >= 0 && percent <= 1)
                toolbar.setBackgroundColor(Color.argb((int) (255.0 * percent), r, g, b));
        }
    });
person Misagh    schedule 17.07.2017
comment
Палец вверх за рисунок. - person azizbekian; 17.07.2017
comment
какая высота у этого Utility.getScreenHeight(context);? Вы имеете в виду высоту экрана устройства? - person Vivek Barai; 12.06.2018
comment
@VivekBarai Да, Utility.getScreenHeight() возвращает высоту экрана устройства. - person Misagh; 18.06.2018
comment
Использование собственной высоты экрана в этой формуле кажется немного ненужным, поскольку процент прокрутки зависит только от содержимого ScrollView. Вот почему вы должны учитывать высоту строки состояния. @JimmyCram имеет более простую формулу, которая гораздо более переносима, поскольку она является автономной для ScrollView. Ваш расчет цвета имеет смысл, но я бы использовал служебные функции Color.red(), Color.green() и Color.blue() вместо битовых операций, чтобы код оставался читабельным и надежным. - person flamewave000; 24.05.2019

попробуй это

scrollview.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                double scrollViewHeight = scrollview.getChildAt(0).getBottom() - scrollview.getHeight();
                double getScrollY = scrollview.getScrollY();
                double scrollPosition = (getScrollY / scrollViewHeight) * 100d;
                Log.i("scrollview", "scroll Percent Y: " + (int) scrollPosition);
            }
        });

он покажет процент от 0 до 100%

person Jimmy Cram    schedule 07.12.2018
comment
Можете ли вы объяснить, почему мы должны использовать scrollview.getChildAt(0).getBottom() - scrollview.getHeight()? Scrollview.getheight не возвращает нужную нам высоту? - person Belphegor; 18.08.2020
comment
О, я вижу, что это для расчета того, сколько вы можете прокрутить на самом деле. - person Belphegor; 18.08.2020

Попробуйте этот метод:

    nestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
                int verticalScrollableHeight = v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight();
                float verticalPercentage = ((float) scrollY) / verticalScrollableHeight;
person Maxim Firsoff    schedule 23.12.2020
comment
Это следует считать правильным ответом. - person Lucas Orso; 15.07.2021