Узнайте, прокручивается ли ListView до конца? - PullRequest
101 голосов
/ 26 февраля 2011

Могу ли я узнать, прокручивается ли мой ListView вниз?Под этим я подразумеваю, что последний элемент полностью виден.

Ответы [ 23 ]

165 голосов
/ 26 февраля 2011

Отредактировано :

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

Реализуйте OnScrollListener, установите ListView 'onScrollListener, и тогда вы сможете правильно обрабатывать вещи.

Например:

private int preLast;
// Initialization stuff.
yourListView.setOnScrollListener(this);

// ... ... ...

@Override
public void onScroll(AbsListView lw, final int firstVisibleItem,
        final int visibleItemCount, final int totalItemCount)
{

    switch(lw.getId()) 
    {
        case R.id.your_list_id:     

            // Make your calculation stuff here. You have all your
            // needed info from the parameters of this function.

            // Sample calculation to determine if the last 
            // item is fully visible.
            final int lastItem = firstVisibleItem + visibleItemCount;

            if(lastItem == totalItemCount)
            {
                if(preLast!=lastItem)
                {
                    //to avoid multiple calls for last item
                    Log.d("Last", "Last");
                    preLast = lastItem;
                }
            }
    }
}
68 голосов
/ 20 апреля 2012

Поздний ответ, но если вы просто хотите проверить, прокручивается ли ваш ListView полностью или нет, не создавая прослушиватель событий, вы можете использовать этот оператор if:

if (yourListView.getLastVisiblePosition() == yourListView.getAdapter().getCount() -1 &&
    yourListView.getChildAt(yourListView.getChildCount() - 1).getBottom() <= yourListView.getHeight())
{
    //It is scrolled all the way down here

}

Сначалапроверяет, видна ли последняя возможная позиция.Затем он проверяет, совпадает ли нижняя часть последней кнопки с нижней частью ListView.Вы можете сделать что-то похожее, чтобы узнать, все ли вверху:

if (yourListView.getFirstVisiblePosition() == 0 &&
    yourListView.getChildAt(0).getTop() >= 0)
{
    //It is scrolled all the way up here

}
16 голосов
/ 13 июля 2015

Как я это сделал:

listView.setOnScrollListener(new AbsListView.OnScrollListener() {

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE 
            && (listView.getLastVisiblePosition() - listView.getHeaderViewsCount() -
            listView.getFooterViewsCount()) >= (adapter.getCount() - 1)) {

        // Now your listview has hit the bottom
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }
});
10 голосов
/ 23 апреля 2011

Что-то с эффектом:

if (getListView().getLastVisiblePosition() == (adapter.items.size() - 1))
6 голосов
/ 31 июля 2016
public void onScrollStateChanged(AbsListView view, int scrollState)        
{
    if (!view.canScrollList(View.SCROLL_AXIS_VERTICAL) && scrollState == SCROLL_STATE_IDLE)    
    {
        //When List reaches bottom and the list isn't moving (is idle)
    }
}

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

4 голосов
/ 20 августа 2014

Это может быть

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                // TODO Auto-generated method stub

                if (scrollState == 2)
                    flag = true;
                Log.i("Scroll State", "" + scrollState);
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                // TODO Auto-generated method stub
                if ((visibleItemCount == (totalItemCount - firstVisibleItem))
                        && flag) {
                    flag = false;



                    Log.i("Scroll", "Ended");
                }
            }
3 голосов
/ 13 июля 2013

Было довольно больно иметь дело с прокруткой, определять, когда она закончена, и она действительно находится внизу списка (не внизу видимого экрана), и запускает мой сервис только один раз, чтобы получить данные из Интернета. Однако сейчас он работает нормально. Кодекс следующий для пользы любого, кто сталкивается с такой же ситуацией.

ПРИМЕЧАНИЕ. Мне пришлось переместить код, связанный с моим адаптером, в onViewCreated вместо onCreate и обнаружить прокрутку в основном так:

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    if (getListView().getLastVisiblePosition() == (adapter.getCount() - 1))
        if (RideListSimpleCursorAdapter.REACHED_THE_END) {
            Log.v(TAG, "Loading more data");
            RideListSimpleCursorAdapter.REACHED_THE_END = false;
            Intent intent = new Intent(getActivity().getApplicationContext(), FindRideService.class);
            getActivity().getApplicationContext().startService(intent);
        }
}

Здесь RideListSimpleCursorAdapter.REACHED_THE_END - это дополнительная переменная в моем SimpleCustomAdapter, которая установлена ​​следующим образом:

if (position == getCount() - 1) {
      REACHED_THE_END = true;
    } else {
      REACHED_THE_END = false;
    }

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

3 голосов
/ 10 сентября 2015

canScrollVertically(int direction) работает для всех видов и, похоже, выполняет то, что вы просили, с меньшим количеством кода, чем большинство других ответов. Вставьте положительное число, и если результат ложный, вы внизу.

есть:

if (!yourView.canScrollVertically(1)) { //you've reached bottom }

2 голосов
/ 26 марта 2015

Я пока не могу комментировать, потому что у меня недостаточно репутации, но в ответе @Ali Imran и @Wroclai я думаю, что чего-то не хватает.С этим фрагментом кода, когда вы обновите preLast, он больше никогда не выполнит журнал.В моей конкретной задаче я хочу выполнять какую-то операцию каждый раз, когда я прокручиваю до конца, но как только preLast обновляется до LastItem, эта операция больше никогда не выполняется.

private int preLast;
// Initialization stuff.
yourListView.setOnScrollListener(this);

// ... ... ...

@Override
public void onScroll(AbsListView lw, final int firstVisibleItem,
                 final int visibleItemCount, final int totalItemCount) {

switch(lw.getId()) {
    case android.R.id.list:     

        // Make your calculation stuff here. You have all your
        // needed info from the parameters of this function.

        // Sample calculation to determine if the last 
        // item is fully visible.
         final int lastItem = firstVisibleItem + visibleItemCount;
       if(lastItem == totalItemCount) {
          if(preLast!=lastItem){ //to avoid multiple calls for last item
            Log.d("Last", "Last");
            preLast = lastItem;
          }
       } else {
            preLast = lastItem;
}

}

С этим «другим» вы теперь можете выполнять свой код (в данном случае, Log) каждый раз, когда снова прокручиваете вниз.

2 голосов
/ 24 августа 2013

Чтобы немного расширить один из приведенных выше ответов, я должен был сделать это, чтобы он работал полностью.Кажется, что внутри ListViews есть около 6 dp встроенных отступов, и onScroll () вызывался, когда список был пустым.Это обрабатывает обе эти вещи.Возможно, его можно немного оптимизировать, но для большей ясности оно написано.

Примечание: я испробовал несколько различных методов преобразования dp в пиксели, и этот dp2px () был лучшим.

myListView.setOnScrollListener(new OnScrollListener() {
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (visibleItemCount > 0) {
            boolean atStart = true;
            boolean atEnd = true;

            View firstView = view.getChildAt(0);
            if ((firstVisibleItem > 0) ||
                    ((firstVisibleItem == 0) && (firstView.getTop() < (dp2px(6) - 1)))) {
                // not at start
                atStart = false;
            }

            int lastVisibleItem = firstVisibleItem + visibleItemCount;
            View lastView = view.getChildAt(visibleItemCount - 1);
            if ((lastVisibleItem < totalItemCount) ||
                    ((lastVisibleItem == totalItemCount) &&
                            ((view.getHeight() - (dp2px(6) - 1)) < lastView.getBottom()))
                    ) {
                        // not at end
                    atEnd = false;
                }

            // now use atStart and atEnd to do whatever you need to do
            // ...
        }
    }
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }
});

private int dp2px(int dp) {
    return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...