我如何创建一个列表,当你到达列表的末尾时,我会收到通知,这样我就可以加载更多的项目?
当前回答
我知道这是一个老问题,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元素,可以单击它从url中获取更多数据。 当按照代码中描述的位置放置时,适配器确切地知道何时显示该按钮,何时禁用该按钮。只需在xml中创建按钮,并按照上面适配器代码所示的方式放置它。
享受。
其他回答
可能有点晚了,但下面的解决方案在我的情况下非常有用。 在某种程度上,所有你需要做的是添加到你的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");
}
});
当页脚可见时,此事件会触发一次,效果非常好。
下面是一个解决方案,它也可以很容易地在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。您可以直接使用这个类,也可以从它扩展。
一种解决方案是实现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应用程序)。
你可以在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上运行)
在Ognyan Bankov GitHub我发现了一个简单而有效的解决方案!
它利用了Volley HTTP库,使Android应用程序的网络更容易,更重要的是,更快。Volley可以通过开放的AOSP存储库获得。
给定的代码演示:
由HTTP分页请求填充的ListView。 NetworkImageView的使用。 “无尽”的ListView分页预读。
为了将来的一致性,我分叉了班科夫的回购。
推荐文章
- 如何在新的材质主题中改变背面箭头的颜色?
- androidviewpager与底部点
- 相同的导航抽屉在不同的活动
- 如何从视图中获得托管活动?
- 单一的TextView与多种颜色的文本
- 如何在非活动类(LocationManager)中使用getSystemService ?
- 在清单中注册应用程序类?
- Android:从数组中编程创建旋转器
- Android命令行工具sdkmanager总是显示:警告:无法创建设置
- 如何设置RecyclerView应用程序:layoutManager=""从XML?
- 在没有开发服务器的情况下在设备上构建和安装unsigned apk ?
- 操作栏和新引入的工具栏有什么不同?
- 调整浮动动作按钮图标大小(fab)
- Android Studio无法找到有效的Jvm(与MAC OS相关)
- android:在触摸移动时移动视图