План действий
- Подготавливаем layout для элемента сообщения о процессе загрузки
- Подготавливаем контрол ListView
- Добавляем в адаптер списка код запуска загрузки следующей страницы
- Обрабатываем результат загрузки очередной страницы
Подготавливаем layout для элемента сообщения о процессе загрузки
Создаем layout xml с двумя элементами ProgressBar с установленным флагом indeterminateOnly и TextView с текстом «Идет загрузка...». Помещаем их в горизонтальный LinearLayout. Можно использовать и уже готовый layout для пустого списка для информации о начальной загрузке.
Подготавливаем ListView
Загружаем подготовленный layout и устанавливаем его подвальным для нашего ListView. Это надо сделать до вызова метода setAdapter. Не забудем сохранить ссылку на элемент, чтобы удалить при достижении конца списка.
private LinearLayout mLoadingFooter; @Override protected void onCreate(Bundle savedInstanceState) { ... LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mLoadingFooter = (LinearLayout) layoutInflater.inflate(R.layout.loading, null); mList = (ListView) findViewById(R.id.list); mList.addFooterView(mLoadingFooter); ... }
Добавляем в адаптер списка код запуска загрузки следующей страницы
Для запуска загрузки следующей страницы используем метод getView адаптера списка: если затребован последний элемент списка, то время грузить следующую страницу. Процесс загрузки удобно убрать в отдельный тред и затем кинуть Intent в текущую активити. Не забудем вызывать notifyDataSetInvalidated если во время загрузки данные, к которым обращается адаптер будут изменяться.
@Override public View getView(int position, View convertView, ViewGroup parent) { ... if (position == getCount() - 1 && hasNextPage()) { loadNextPage(); } }
UPD: grishkaa рекомендовал более правильный способ с использованием AbsListView.OnScrollListener:
mList.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView arg0, int arg1) {} @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (visibleItemCount > 0 && firstVisibleItem + visibleItemCount == totalItemCount && hasNextPage()) { loadNextPage(); } } });
Обрабатываем результат загрузки очередной страницы
Intent можно перехватить анонимным BroadcastReceiver и передать в Handler (чтобы исполнить в UI треде). Нам остается только вызвать метод notifyDataSetChanged адаптера и удалить подвальный элемент, если загружена последняя страница.
if (!hasNextPage() && mList.getFooterViewsCount() > 0) { mList.removeFooterView(mLoadingFooter); } mAdapter.notifyDataSetChanged();
