我如何创建一个列表,当你到达列表的末尾时,我会收到通知,这样我就可以加载更多的项目?


当前回答

一种解决方案是实现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;
        }
    }
}

显然,对于长时间运行的操作(如加载web-data),您应该使用单独的线程,并可能希望在最后一个列表项中指示进度(如市场或gmail应用程序)。

其他回答

下面是一个解决方案,它也可以很容易地在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 - EndlessListView。您可以直接使用这个类,也可以从它扩展。

I've been working in another solution very similar to that, but, I am using a footerView to give the possibility to the user download more elements clicking the footerView, I am using a "menu" which is shown above the ListView and in the bottom of the parent view, this "menu" hides the bottom of the ListView, so, when the listView is scrolling the menu disappear and when scroll state is idle, the menu appear again, but when the user scrolls to the end of the listView, I "ask" to know if the footerView is shown in that case, the menu doesn't appear and the user can see the footerView to load more content. Here the code:

的问候。

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) {

    }
});

这个问题的关键是检测load-more事件,启动数据异步请求,然后更新列表。还需要一个带有加载指示器和其他装饰器的适配器。事实上,在一些极端情况下,这个问题非常复杂。只有OnScrollListener实现是不够的,因为有时项目不会填满屏幕。

我写了一个个人包,它支持无限列表的RecyclerView,也提供了一个异步加载器实现AutoPagerFragment,这使得它很容易从多页源获取数据。它可以将任何页面加载到自定义事件的RecyclerView中,而不仅仅是下一页。

这是地址:https://github.com/SphiaTower/AutoPagerRecyclerManager

可能有点晚了,但下面的解决方案在我的情况下非常有用。 在某种程度上,所有你需要做的是添加到你的ListView页脚,并为它创建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");
    }
});

当页脚可见时,此事件会触发一次,效果非常好。

你可以在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()来更新视图(它应该在UI线程runOnUiThread上运行)