2009-07-03 2 views
220

Как создать список, где, когда вы дойдете до конца списка, я получаю уведомление, чтобы загрузить больше предметов?Android Endless List

+9

Я рекомендую EndWare EndWare: http://github.com/commonsguy/cwac-endless. Я нашел это из этого ответа на другой вопрос: http://stackoverflow.com/questions/4667064/android-implementing-endless-list-like-android-market/4667102#4667102. –

+0

Мне нужно то же самое ... можно ли кому-нибудь помочь? ..http: //stackoverflow.com/questions/28122304/endless-scrolling-listview-not-working – 2015-01-30 04:00:55

ответ

266

Одним из решений является внедрение OnScrollListener и внесение изменений (например, добавление элементов и т. Д.) В ListAdapter в удобном состоянии в его методе onScroll.

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

public class Test extends ListActivity implements OnScrollListener { 

    Aleph0 adapter = new Aleph0(); 

    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setListAdapter(adapter); 
     getListView().setOnScrollListener(this); 
    } 

    public void onScroll(AbsListView view, 
     int firstVisible, int visibleCount, int totalCount) { 

     boolean loadMore = /* maybe add a padding */ 
      firstVisible + visibleCount >= totalCount; 

     if(loadMore) { 
      adapter.count += visibleCount; // or any other amount 
      adapter.notifyDataSetChanged(); 
     } 
    } 

    public void onScrollStateChanged(AbsListView v, int s) { }  

    class Aleph0 extends BaseAdapter { 
     int count = 40; /* starting amount */ 

     public int getCount() { return count; } 
     public Object getItem(int pos) { return pos; } 
     public long getItemId(int pos) { return pos; } 

     public View getView(int pos, View v, ViewGroup p) { 
       TextView view = new TextView(Test.this); 
       view.setText("entry " + pos); 
       return view; 
     } 
    } 
} 

Вы должны явно использовать отдельные потоки для длительных действий (например, загрузки веб-данных) и, возможно, требуется указать прогресс в последнем элементе списка (например, на рынке или Gmail приложения делают).

+3

huh, не приведет ли это к увеличению размера адаптера, d остановить прокрутку в середине экрана? он должен загружать только следующие 10 при фактическом достижении нижней части списка. – Matthias

+9

Я замечаю много примеров, подобных этому, используя BaseAdapter. Хотел бы упомянуть, что если вы используете базу данных, попробуйте использовать SimpleCursorAdapter. Когда вам нужно добавить в список, обновите свою базу данных, получите новый курсор и используйте SimpleCursorAdapter # changeCursor вместе с notifyDataSetChanged. Не требуется никакого подкласса, и он работает лучше, чем BaseAdapter (опять же, только если вы используете базу данных). – brack

+1

После вызова notifyDataSetChanged() он перейдет в начало списка, как я могу его предотвратить? – draw

20

Вы можете обнаружить конец списка с помощью onScrollListener, рабочий код представлен ниже:

@Override 
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
    if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) { 
     Log.v(TAG, "onListEnd, extending list"); 
     mPrevTotalItemCount = totalItemCount; 
     mAdapter.addMoreData(); 
    } 
} 

Другой способ сделать это (внутри адаптера) выглядит следующим образом:

public View getView(int pos, View v, ViewGroup p) { 
      if(pos==getCount()-1){ 
       addMoreData(); //should be asynctask or thread 
      } 
      return view; 
    } 

Be что этот метод будет вызываться много раз, поэтому вам нужно добавить еще одно условие для блокировки нескольких вызовов addMoreData().

При добавлении всех элементов в список, пожалуйста, позвоните notifyDataSetChanged() внутри Yours адаптера для обновления View (он должен быть запущен на UI потоке - runOnUiThread)

+0

Редактировать: добавлен метод getView() –

+7

Неплохая практика делать другие вещи, чем возвращать представление в 'getView'. Например, вам не гарантируется, что пользователь 'pos' просматривается. Это может быть просто измерительный материал ListView. –

+0

Я хочу загрузить больше предметов после прокрутки 10 элементов. но я замечаю, что загрузка начинается до того, как будет отображаться 10-й элемент, на 9-м элементе. Так как это остановить? –

91

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

Он также основан на интерфейсе OnScrollListener, но я обнаружил, что он имеет гораздо лучшую производительность прокрутки на устройствах младшего класса, так как ни одна из видимых/итоговых подсчетов не выполняется во время операций прокрутки.

  1. Пусть ваш ListFragment или ListActivity реализовать OnScrollListener
  2. Добавьте следующие методы к этому классу:

    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, 
         int visibleItemCount, int totalItemCount) { 
        //leave this empty 
    } 
    
    @Override 
    public void onScrollStateChanged(AbsListView listView, int scrollState) { 
        if (scrollState == SCROLL_STATE_IDLE) { 
         if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) { 
          currentPage++; 
          //load more list items: 
          loadElements(currentPage); 
         } 
        } 
    } 
    

    где currentPage страница вашего источника данных, которые должны быть добавлены в список, и threshold - количество элементов списка (отсчитывается с конца), которое должно, если оно видимо, запускать процесс загрузки. Если вы установили threshold на номер 0, пользователь должен прокрутить страницу до самого конца списка, чтобы загрузить больше предметов.

  3. (необязательно) Как вы можете видеть, «проверка нагрузки больше» вызывается только тогда, когда пользователь прекращает прокрутку. Чтобы улучшить удобство использования, вы можете раздуть и добавить индикатор загрузки в конец списка через listView.addFooterView(yourFooterView). Одним из примеров такого взгляда колонтитула:

    <?xml version="1.0" encoding="utf-8"?> 
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
        android:id="@+id/footer_layout" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:padding="10dp" > 
    
        <ProgressBar 
         android:id="@+id/progressBar1" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:layout_centerVertical="true" 
         android:layout_gravity="center_vertical" /> 
    
        <TextView 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:layout_centerVertical="true" 
         android:layout_toRightOf="@+id/progressBar1" 
         android:padding="5dp" 
         android:text="@string/loading_text" /> 
    
    </RelativeLayout> 
    
  4. (необязательно) Наконец, удалите этот индикатор загрузки путем вызова listView.removeFooterView(yourFooterView) если нет больше элементов или страниц.

+0

Я пробовал это, но он не работает для ListFragment. Как его можно использовать в ListFragment. – zeeshan

+0

Ну, я также использую его с «ListFragment», без проблем - просто следуйте каждому из приведенных выше шагов, и все будет хорошо;) Или вы могли бы предоставить какие-либо сообщения об ошибках? – saschoar

+0

Что вы, возможно, пропустили, объясняется в этом SO-ответе: http://stackoverflow.com/a/6357957/1478093 - 'getListView(). SetOnScrollListener (this)' – TBieniek

0

Я работал в другом решении очень похоже на то, но, я использую footerView, чтобы дать возможность пользователю загрузить дополнительные элементы, нажав на footerView, я использую «меню», которое показанный выше ListView и в нижней части родительского вида, это «меню» скрывает нижнюю часть ListView, поэтому, когда прокрутка listView прокручивается, меню исчезает, а когда состояние прокрутки простаивает, меню появляется снова, но когда пользователь прокручивается до конца listView, я «спрашиваю», чтобы узнать, отображается ли в этом случае footerView, меню не отображается, и пользователь может видеть footerView для загрузки большего содержимого. Здесь код:

С уважением.

listView.setOnScrollListener(new OnScrollListener() { 

    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) { 
     // TODO Auto-generated method stub 
     if(scrollState == SCROLL_STATE_IDLE) { 
      if(footerView.isShown()) { 
       bottomView.setVisibility(LinearLayout.INVISIBLE); 
      } else { 
       bottomView.setVisibility(LinearLayout.VISIBLE); 
      } else { 
       bottomView.setVisibility(LinearLayout.INVISIBLE); 
      } 
     } 
    } 

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

    } 
}); 
2

Вот решение, которое также позволяет легко показать вид нагрузки в конце ListView, пока она загружается.

Вы можете видеть классы здесь:

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Helper, чтобы сделать возможным использовать функции без расширения от SimpleListViewWithLoadingIndicator.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Слушатель, который начинает загрузку данных, когда пользователь достигнет нижней части ListView.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. Вы можете использовать этот класс напрямую или от него.

4

В Ognyan Bankov GitHub Я нашел простое и рабочее решение!

Он использует Volley HTTP library, что упрощает работу сети для приложений Android, а главное - быстрее. Волейбол доступен через открытый репозиторий AOSP.

Данный код показывает:

  1. ListView, который заполняется по HTTP страничных запросов.
  2. Использование NetworkImageView.
  3. «Бесконечный» ListView с разбивкой по страницам с возможностью чтения вперед.

Для будущей консистенции i forked Bankov's repo.

0

Ключом этой проблемы является обнаружение события load-more, запуск асинхронного запроса данных, а затем обновление списка. Также необходим адаптер с индикатором загрузки и другими декораторами. На самом деле проблема в некоторых случаях имеет очень сложную задачу. Просто реализация OnScrollListener недостаточна, потому что иногда элементы не заполняют экран.

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

Вот адрес: https://github.com/SphiaTower/AutoPagerRecyclerManager

+0

Ссылка не работает. – DSlomer64

1

Может быть немного поздно, но следующее решение было очень полезным в моем случае. В любом случае вам нужно добавить в ListView Footer и создать для него addOnLayoutChangeListener.

http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)

Например:

ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView 
View loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more, null); // Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout. 
listView1.addFooterView(loadMoreView); // Adding your View to your listview 

... 

loadMoreView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
    @Override 
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
     Log.d("Hey!", "Your list has reached bottom"); 
    } 
}); 

пожаров Этого события один раз, когда сноска становится видимой и работает как шарм.

0

Лучшее решение, которое я видел, находится в библиотеке FastAdapter для просмотра recycler. Он имеет EndlessRecyclerOnScrollListener.

Вот пример использования: EndlessScrollListActivity

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