как определить положение прокрутки вложенного прокрутки андроида внизу?

Я просто хочу определить положение прокрутки вложенного прокрутки Android внизу и функцию вызова. мой код:

scroll.getViewTreeObserver()
      .addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
           @Override
           public void onScrollChanged() {
               int totalHeight = scroll.getChildAt(0).getHeight();
               int scrollY = scroll.getScrollY();
               Log.v("position", "totalHeight=" + totalHeight + "scrollY=" + scrollY);
               if (scrollY==totalHeight) {
                   getPlaylistFromServer("more");
               }
           }
      });

но общая высота не совпадает с MAX ScrollY. как это исправить?


person Amay Diam    schedule 21.03.2016    source источник
comment
Используйте 1_   -  person Nikola Despotoski    schedule 23.03.2016
comment
Поскольку ViewCompat.canScrollVertically(View v, int direction) устарел, используйте View.canScrollVertically(int direction).   -  person Ankit Gupta    schedule 10.05.2021


Ответы (8)


Установите setOnScrollChangeListener в параметрах NestedScrollView, чтобы получить

  • NestedScrollView v (родительский элемент с прокруткой)
  • интервал прокруткиY
  • int oldScrollY

Чтобы определить, находится ли смещение внизу, необходимо получить значение высоты содержимого v.getChildAt(0).getMeasuredHeight() и сравнить текущий скролл с высотой родителя, если у вас одинаковое значение, значит, он дошел до конца.

Вы можете получить высоту с родительским видом с помощью v.getMeasuredHeight()

NestedScrollView scroller = (NestedScrollView) findViewById(R.id.myScroll);

if (scroller != null) {

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

            if (scrollY > oldScrollY) {
                Log.i(TAG, "Scroll DOWN");
            }
            if (scrollY < oldScrollY) {
                Log.i(TAG, "Scroll UP");
            }

            if (scrollY == 0) {
                Log.i(TAG, "TOP SCROLL");
            }

           if (scrollY == ( v.getMeasuredHeight() - v.getChildAt(0).getMeasuredHeight() )) {
               Log.i(TAG, "BOTTOM SCROLL");
           }
       }
    });
}
person Webserveis    schedule 04.06.2016
comment
Как проверить, когда пользователь перестал прокручивать, например, когда он простаивает? - person Alaa AbuZarifa; 24.08.2017
comment
Кто-нибудь может объяснить, почему эта линия работает? if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) Как получается, что измеренная высота NestedScrollView меньше высоты содержимого, хотя NestedScrollView является родителем? - person coolDude; 10.03.2018
comment
намного лучше v.getMeasuredHeight() - v.getChildAt(0).getMeasuredHeight(, я меняю сейчас - person Webserveis; 10.03.2018
comment
min API для этого подхода — 23, знаете ли вы другую альтернативу? - person João Carlos; 07.08.2018
comment
@JoãoCarlos, нет, это не из 23 API. setOnScrollChangeListener(View.OnScrollChangeListener) нужен API 23, а setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener) нет - person grine4ka; 30.04.2020
comment
Ты герой моего дня, бро! Ваш ответ мне очень помог. Спасибо! - person Mark Delphi; 02.10.2020

Я знаю, что уже поздно, но... попробуй так.

scroll.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
            View view = (View) scroll.getChildAt(scroll.getChildCount() - 1);

            int diff = (view.getBottom() - (scroll.getHeight() + scroll
                    .getScrollY()));

            if (diff == 0) {
                getPlaylistFromServer("more");
            }          
    }
});

Удачного кодирования..

person V-rund Puro-hit    schedule 03.06.2016
comment
Спасибо. Это спасет мой день. - person Mahmudur Rahman; 14.01.2020
comment
Если у вас есть recyclerview в режиме вложенной прокрутки. Пожалуйста, обратитесь к этому. - person Abhinav Upadhyay; 02.03.2020

Webserveis ответил правильно, но ему нужно немного изменить onScrollChange (метод переопределения), например:

if (scrollY === v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()) {
   // end of the scroll view
}

Котлин:

if (scrollY == v.getChildAt(0).measuredHeight - v.measuredHeight) {
    // end of the scroll view
}
person Wai Yan    schedule 29.04.2019

  @Override
public void onScrollChange(NestedScrollView nestedScrollView, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
    if (nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1) != null) {
        if ((scrollY >= (nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1).getMeasuredHeight() - nestedScrollView.getMeasuredHeight())) &&
                scrollY > oldScrollY) {
            LogsUtils.INSTANCE.makeLogD(">onScrollChange>", ">>BOTTOm");
        }

    }
}

У меня это сработало, Источник

person vishnu t satheesh    schedule 06.12.2018

Это сработало для меня:

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

            if (v.getChildAt(0).getBottom()<=(nestedScroll.getHeight()+scrollY)) {
                System.out.println("End of NestedScrollView");
            }

        }
    });

По сути, мы добавляем множество представлений внутрь вложенногоScrollView, но объединяем их вместе в форме одного представления. Следовательно, childCount всегда будет равен 1 с его индексом 0. Таким образом, используется v.getChildAt(0).getBottom() для определения его дна. Теперь nestedScroll.getHeight() возвращает высоту в пикселях, а scrollY возвращает текущее вертикальное начало. Следовательно, указанное выше условие будет выполняться каждый раз, когда будет достигнута нижняя часть NestedScrollView.

if (v.getChildAt(0).getBottom()==(nestedScroll.getHeight()+nestedScroll.getScrollY()))

Это работает только некоторое время... поэтому не используйте его таким образом.

person Mrudul Tora    schedule 31.10.2020

для API ‹ 23 вы можете добавить в treeObserver.scrollChangeLister хранилище локальной переменной с плавающей запятой и проверить, как вы прокручиваете, как это

пример

public class About extends AppCompatActivity implements 
ViewTreeObserver.OnScrollChangedListener{

private float viewScrolled = 0;

   nestedScrollView.getViewTreeObserver().addOnScrollChangedListener(this);

}

@Override
public void onScrollChanged() {

    if (viewScrolled < nestedScrollView.getScrollY()){
        viewScrolled = nestedScrollView.getScrollY();
        Log.d(TAG, "scrolling up");
    }
    if (viewScrolled > nestedScrollView.getScrollY()){
        viewScrolled = nestedScrollView.getScrollY();
        Log.d(TAG, "scrolling down");
    }
}
person martinseal1987    schedule 14.06.2019

Webserveis ответил правильно, но условие должно быть таким

 if (scrollY == (v?.getChildAt(0)?.measuredHeight ?: 0) - (v?.measuredHeight ?: 0)) {
    //at bottom
    }
person sandeep dhami    schedule 09.04.2020

Это сработало для меня!

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



                    if (scrollY == v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()) {
                        Log.d(TAG, "onScrollChange: SRCOLLED ==> scrollY: ======================================> THIS IS THE VERY END ");
                    }

                

            }
        });
person MUHINDO    schedule 10.02.2021