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
接口,但是我发现它在低端设备上有更好的滚动性能,因为在滚动操作期间没有进行可见/总计数计算。
- 让你的
ListFragment
或ListActivity
实现OnScrollListener
-
将以下方法添加到该类中:
@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
,则用户必须滚动到列表的最后才能加载更多项目。 -
(可选)正如你所看到的,只有当用户停止滚动时才会调用“加载更多检查”。 为了提高可用性,您可以通过
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>
-
(可选)最后,如果没有更多的项目或页面,则通过调用
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存储库获得。
给定的代码演示:
- ListView由HTTP分页请求填充。
- NetworkImageView的使用。
- “无尽的”ListView分页与预读。
为了未来的一致性,我分叉了Bankov的回购 。
这是一个解决scheme,它也使得在加载ListView的末尾显示加载视图变得非常容易。
你可以在这里看到这些课程:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java – 帮手,使之有可能使用没有从SimpleListViewWithLoadingIndicator扩展的function。
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。 你可以直接使用这个类,或者直接使用这个类。
可能会有点晚,但下面的解决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) { } });
- 如何保护我的应用程序免受盗版
- Android“只有创build视图层次结构的原始线程才能触及其视图。”
- 使用Android播放任意音
- 将EditText imeOptions设置为actionNext不起作用
- 如何在其他国家探索基于networking的Google Play?
- 如何模仿材质devise凸起的button风格,即使是前棒棒糖(减去特殊效果)?
- 使用具有ClassLoader作为参数的Parcel.read方法时,“BadParcelableException:解组时使用ClassNotFoundException”<unclassified> <myclass>
- 从应用程序以编程方式启动Skype并传递号码 – Android
- Android中的全屏DialogFragment