Android无尽列表

我如何创build一个列表,当你到达列表的末尾,我收到通知,所以我可以加载更多的项目?

一种解决scheme是实现一个OnScrollListener并在其onScroll方法中以方便的状态对ListAdapter进行更改(如添加项目等)。

以下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数据),并可能希望在最后一个列表项(如市场或Gmail应用程序)中指示进度。

只是想贡献一个我用于我的应用程序的解决scheme。

它也基于OnScrollListener接口,但是我发现它在低端设备上有更好的滚动性能,因为在滚动操作期间没有进行可见/总计数计算。

  1. 让你的ListFragmentListActivity实现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)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)移除该加载指示器。

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

Ognyan Bankov GitHub我发现了一个简单而有效的解决scheme!

它利用了Volley HTTP library ,使得Android应用程序的联网更加简单,最重要的是更快。 Volley可通过开放的AOSP存储库获得。

给定的代码演示:

  1. ListView由HTTP分页请求填充。
  2. NetworkImageView的使用。
  3. “无尽的”ListView分页与预读。

为了未来的一致性,我分叉了Bankov的回购 。

这是一个解决scheme,它也使得在加载ListView的末尾显示加载视图变得非常容易。

你可以在这里看到这些课程:

https://github.com/Cyber​​Eagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java – 帮手,使之有可能使用没有从SimpleListViewWithLoadingIndicator扩展的function。

https://github.com/Cyber​​Eagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java – 当用户开始加载数据的监听器即将到达ListView的底部。

https://github.com/Cyber​​Eagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java – EndlessListView。 你可以直接使用这个类,或者直接使用这个类。

可能会有点晚,但下面的解决scheme发生在我的情况非常有用。 在某种程度上,所有你需要做的就是添加到你的ListView Footer并为它创buildaddOnLayoutChangeListener

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. Eg 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"); } }); 

当页脚变得可见并且像魅力一样工作时,这个事件就会触发一次。

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

我已经写了一个支持RecyclerView无限列表的个人包,还提供了一个asynchronous加载器实现AutoPagerFragment ,这使得从多页源获取数据变得非常容易。 它可以将你想要的任何页面加载到自定义事件的RecyclerView ,而不仅仅是下一页。

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

到目前为止,我所见过的最佳解决scheme是在FastAdapter库中进行回收器视图。 它有一个EndlessRecyclerOnScrollListener

这是一个示例用法: EndlessScrollListActivity

一旦我用它无尽的滚动列表,我已经意识到,设置是一个非常强大的。 我肯定会推荐它。

我一直工作在另一个解决scheme非常相似,但是,我正在使用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) { } });