it-swarm.com.ru

Бесконечный список Android

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

228
Isaac Waller

Одним из решений является реализация 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;
        }
    }
}

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

268
Josef Pfleger

Просто хотел предложить решение, которое я использовал для своего приложения.

Он также основан на интерфейсе 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), если больше нет элементов или страниц.

93
saschoar

Вы можете определить конец списка с помощью 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;
    }

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

Когда вы добавляете все элементы в список, пожалуйста, вызовите notifyDataSetChanged () внутри вашего адаптера, чтобы обновить представление (его следует запускать в потоке пользовательского интерфейса - runOnUiThread )

20
Dariusz Bacinski

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

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

Данный код демонстрирует:

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

Для будущей консистенции я раздвоил репо Банкова .

4
oikonomopo

Вот решение, которое также облегчает отображение представления загрузки в конце 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 - Listener который начинает загрузку данных, когда пользователь собирается достичь нижней части ListView.

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

2
Fernando Camargo

Может быть, немного поздно, но следующее решение оказалось очень полезным в моем случае .. Все, что вам нужно сделать, это добавить в свой 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");
    }
});

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

1
tehcpu

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

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

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

0
Shubham Chaudhary

Я работал над другим решением, очень похожим на это, но я использую 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) {

    }
});
0
pabloverd

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

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

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

0
ProtossShuttle