简介
Android系统支持的ListView只负责显示数据,不支持分页显示。而使其情况下列表需要展示的数据可能很多,如果一下子载全部加载完成,会导致效率的降低,甚至会导致内存溢出,因此我们必须实现分页功能。
功能
本文自定的listview支持列表滑到最后一条记录时加载下一页数据。
自定义ListView分页步骤
1 自定义PagerListView继承Android平台ListView,并实现OnScrollListener接口(此接口是列表视图滚动时的一个回调接口),重写或者实现响应的方法。
2 定义底部FView,xml或者代码中,也可以不需要
3 实现回调方法,在回调方法(onScroll)中记录最后一条记录位置和总条数,在回调方法(onScrollStateChanged)中判断是否滚动到最后一条记录,如果是则加载数据。
4 自定义数据加载接口,接受记录起始位置和每页记录数两个参数,此接口由使用者实现,由listview调用,以自动分页。
示例
示例中
AsyncNetRequest是自定义异步请求类,参见 Android异步请求处理实现机制
请求中URL为本地一个请求,可以是任何数据,此请求仅仅模拟远程请求,实际要展示的数据在请求成功后自动生成。
底部View定义
res/layout/pagerlistview_loadmore_footer.xml
android:layout_width="match_parent"
android:layout_height="wrap_content" android:padding="10dp">
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/gray" />
android:id="@+id/loader_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="正在加载..."
android:textSize="18sp" />
android:id="@+id/loader_load"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="点此加载更多"
android:textSize="18sp" />
android:id="@+id/loader_none"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="已显示全部"
android:textSize="18sp" />
PagerListView定义
import com.example.fxgandroid.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
/**
* 自定义ListView,添加分页支持。点击底部提示View或者滚动到底部时加载更多数据
*
* @author fengxiaogang
*
*/
public class PagerListView extends ListView implements OnScrollListener {
// 底部View,正在加载、加载更多、已显示全部数据
private View footerView;
private View loadingView;
private View loadView;
private View noneView;
// 分页大小,默认每页20条记录
private int pageSize = 20;
// 适配器中item总条数
private int totalItemCount = 0;
// 最后可见Item的索引
private int lastVisibleItem = 0;
// 是否正在加载标示
private boolean isLoading = false;
// 是否还有更多数据,默认有
private boolean hasMore = true;
// 回调接口定义,当ListView需要加载更多数据时被调用
private OnLoadListener onLoadListener;
// ---------------------------构造函数---------------------------
public PagerListView(Context context) {
super(context);
initView(context);
}
public PagerListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public PagerListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
// ---------------------------构造函数---------------------------
/**
* 初始化FooterView并为其添加事件监听器、注册OnScrollListener监听器
*
* @param context
*/
private void initView(Context context) {
// 初始化并添加底部View
LayoutInflater inflater = LayoutInflater.from(context);
footerView = inflater.inflate(R.layout.pagerlistview_loadmore_footer,
null);
loadingView = footerView.findViewById(R.id.loader_loading);
loadView = footerView.findViewById(R.id.loader_load);
noneView = footerView.findViewById(R.id.loader_none);
addFooterView(footerView, null, false);
loadView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
load();
}
});
// 注册ScrollListener
setOnScrollListener(this);
}
// ---------------------------OnScrollListener接口两个方法----------------
/**
* 滚动到左后一item时加载下一页数据,并且显示正在加载
*/
public void onScrollStateChanged(AbsListView view, int scrollState) {
//
if (lastVisibleItem == totalItemCount
&& scrollState == SCROLL_STATE_IDLE) {
load();
}
}
/**
* 列表视图滚动式记录最后一个条目的索引和适配器中元素总数
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.lastVisibleItem = firstVisibleItem + visibleItemCount;
this.totalItemCount = totalItemCount;
}
// ---------------------------OnScrollListener接口两个方法----------------
/**
* 加载下一页数据,第一条数据索引为1.
*/
private void load() {
if (!isLoading && hasMore) {
isLoading = true;
showLoadingView();
if (onLoadListener != null) {
int start = lastVisibleItem == 0 ? 1 : lastVisibleItem;
onLoadListener.onLoad(start, pageSize);
}
}
}
/**
* 数据加载接口,当列表View需要加载数据时此接口会被调用
*
* @author fengxiaogang
*
*/
public interface OnLoadListener {
void onLoad(int start, int pageSize);
}
/**
* 设置回调接口,此方法调用后会导致ListView加载第一页(onLoad(start, pageSize)方法被调用)
* @param onLoadListener
*/
public void setOnLoadListener(OnLoadListener onLoadListener) {
this.onLoadListener = onLoadListener;
// 在此时加载第一页
load();
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
/**
* 数据加载完成后调用此方法隐藏底部View
*/
public void loadComplete() {
this.invalidate();
showLoadView();
isLoading = false;
}
/**
* 底部View显示为正在加载
*/
public void showLoadingView() {
loadingView.setVisibility(View.VISIBLE);
loadView.setVisibility(View.GONE);
noneView.setVisibility(View.GONE);
}
/**
* 底部View显示,加载更多
*/
public void showLoadView() {
loadingView.setVisibility(View.GONE);
loadView.setVisibility(View.VISIBLE);
noneView.setVisibility(View.GONE);
}
/**
* 底部View显示 已显示全部
*/
public void showNoneView() {
loadingView.setVisibility(View.GONE);
loadView.setVisibility(View.GONE);
noneView.setVisibility(View.VISIBLE);
}
/**
* 告诉ListView没有更多数据要显示了
* @param hasMore
*/
public void setHasMore(boolean hasMore) {
this.hasMore = hasMore;
}
public void reset(){
hasMore = true;
isLoading = false;
lastVisibleItem=0;
}
}
Bean定义
public class ListItem {
private String title;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
adapter定义
public class DemoAdapter extends BaseAdapter {
private List items;
private Context context;
private LayoutInflater inflater;
public DemoAdapter(Context context, List items) {
this.context = context;
this.items = items;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.pager_listview_item, null);
ListItem item = items.get(position);
TextView txvTitle = (TextView) convertView.findViewById(R.id.title);
TextView txvContent = (TextView) convertView.findViewById(R.id.content);
txvTitle.setText(item.getTitle());
txvContent.setText(item.getContent());
return convertView;
}
}
列表视图子元素视图定义
res/layout/pager_listview_item.xml
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
activity入口定义
public class PagerListViewActivity extends Activity {
private PagerListView pagerListView;
private DemoAdapter adapter;
private List
list = new Vector();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pager_list_view);
initView();
initListener();
}
private void initView() {
pagerListView = (PagerListView) findViewById(R.id.pagerlistview);
adapter = new DemoAdapter(getApplicationContext(), list);
pagerListView.setAdapter(adapter);
}
private void initListener() {
pagerListView.setOnLoadListener(new OnLoadListener() {
@Override
public void onLoad(final int start,final int pageSize
) {
AsyncNetRequest asyncNetRequest = new AsyncNetRequest(getApplicationContext());
asyncNetRequest.setUrl("http://192.168.0.36:8080/demo");
asyncNetRequest.sendRequest(null, new ResponseCallback() {
@Override
public void requestFail() {
}
@Override
public void refreshView() {
for(int i=0;i
ListItem item = new ListItem();
item.setTitle("标题"+i);
item.setContent("内容"+i);
list.add(item);
}
pagerListView.loadComplete();
}
@Override
public void handleResult(String result) {
}
});
}
});
}
}
MainActivity布局文件
res/layout/activity_pager_list_view.xml
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical" >
android:id="@+id/pagerlistview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
运行效果