我如何创建列表,当您到达列表末尾时会收到通知,以便我可以加载更多物品?
我如何创建列表,当您到达列表末尾时会收到通知,以便我可以加载更多物品?
Answers:
一种解决方案是在其方法中以方便的状态实现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;
}
}
}
显然,您应该对长时间运行的操作(例如加载网络数据)使用单独的线程,并且可能希望指示最后一个列表项的进度(例如市场或gmail应用程序)。
firstVisible + visibleCount >= totalCount
通过多次调用侦听器可以多次满足该条件。如果加载更多功能是Web请求(很可能是),请添加另一个检查,以检查请求是否正在进行。另一方面,请检查totalCount是否不等于上一个总数,因为我们不需要列表中相同数量的项目的多个请求。
只是想为我的应用程序提供一个解决方案。
它也是基于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)
。这种页脚视图的一个示例:
<?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)
如果没有更多的项目或页面,则通过调用删除该加载指示器。
ListFragment
也可以毫无问题地使用它-只需按照上述每个步骤进行操作,就可以了;)还是可以提供任何错误消息?
getListView().setOnScrollListener(this)
您可以在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上运行)
getView
。例如,您不能保证pos
被用户查看。它可能只是ListView测量的东西。
在Ognyan Bankov GitHub
我发现一个简单而有效的解决方案!
它利用Volley HTTP library
可使Android应用程序联网更容易,最重要的是,更快。可通过开放的AOSP存储库获得Volley。
给定的代码演示:
为了将来的一致性,我分叉了班科夫的回购协议。
这是一个解决方案,它还使得在加载ListView的末尾轻松显示加载视图。
您可以在此处查看课程:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java- 帮助程序可以使用功能没有扩展自SimpleListViewWithLoadingIndicator。
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java- 当用户开始加载数据的监听器即将到达ListView的底部。
可能有些晚,但是以下解决方案对我而言非常有用。在某种程度上,您需要做的就是添加到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");
}
});
当页脚可见并像吊饰一样工作时,将触发此事件一次。
此问题的关键是检测load-more事件,启动对数据的异步请求,然后更新列表。另外,还需要带有加载指示器和其他装饰器的适配器。实际上,在某些特殊情况下,该问题非常复杂。仅仅一个OnScrollListener
实现是不够的,因为有时项目不能填满整个屏幕。
我写了一个个人软件包,它支持的无穷列表RecyclerView
,并且还提供了一个异步加载器实现AutoPagerFragment
,使从多页源获取数据非常容易。它可以将您想要的任何页面加载到RecyclerView
自定义事件中,而不仅仅是下一页。
这是地址:https : //github.com/SphiaTower/AutoPagerRecyclerManager
到目前为止,我所见过的最佳解决方案是在FastAdapter库中获取回收者视图。它有一个EndlessRecyclerOnScrollListener
。
这是一个示例用法:EndlessScrollListActivity
将其用于无限滚动列表后,我意识到该设置非常可靠。我肯定会推荐它。
我一直在使用与之非常相似的另一种解决方案,但是,我正在使用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世界几乎已经转移到RecyclerViews,但是对于任何感兴趣的人,您可能会发现此库非常有趣。
它使用与ListView一起使用的BaseAdapter来检测何时列表已滚动到最后一个项目,或者何时滚动到远离最后一个项目。
它带有一个示例项目(几乎100行活动代码),可用于快速了解其工作方式。
简单用法:
class Boy{
private String name;
private double height;
private int age;
//Other code
}
用于容纳Boy对象的适配器如下所示:
public class BoysAdapter extends EndlessAdapter<Boy>{
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent
.getContext());
holder = new ViewHolder();
convertView = inflater.inflate(
R.layout.list_cell, parent, false);
holder.nameView = convertView.findViewById(R.id.cell);
// minimize the default image.
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Boy boy = getItem(position);
try {
holder.nameView.setText(boy.getName());
///Other data rendering codes.
} catch (Exception e) {
e.printStackTrace();
}
return super.getView(position,convertView,parent);
}
请注意,BoysAdapter的getView方法如何返回对EndlessAdapter超类的调用。 getView
方法。这是100%必不可少的。
现在创建适配器,执行以下操作:
adapter = new ModelAdapter() {
@Override
public void onScrollToBottom(int bottomIndex, boolean moreItemsCouldBeAvailable) {
if (moreItemsCouldBeAvailable) {
makeYourServerCallForMoreItems();
} else {
if (loadMore.getVisibility() != View.VISIBLE) {
loadMore.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onScrollAwayFromBottom(int currentIndex) {
loadMore.setVisibility(View.GONE);
}
@Override
public void onFinishedLoading(boolean moreItemsReceived) {
if (!moreItemsReceived) {
loadMore.setVisibility(View.VISIBLE);
}
}
};
的 loadMore
项目是一个按钮或其他ui元素,可以单击该按钮或其他ui元素以从URL中获取更多数据。按照代码中的说明放置适配器时,适配器确切知道何时显示该按钮以及何时禁用该按钮。只需在xml中创建按钮并将其放置在上面的适配器代码中即可。
请享用。