Android自定义ListView实现上滑分页
来源:互联网 发布:windows默认字体包 编辑:程序博客网 时间:2024/06/06 01:43
简介
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
<?xml version="1.0" encoding="utf-8"?>
<!-- ListView底部加载更多按钮 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:padding="10dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/gray" />
<!-- 正在加载 -->
<RelativeLayout
android:id="@+id/loader_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="正在加载..."
android:textSize="18sp" />
</RelativeLayout>
<!-- 加载更多 -->
<RelativeLayout
android:id="@+id/loader_load"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="点此加载更多"
android:textSize="18sp" />
</RelativeLayout>
<!-- 已显示全部 -->
<RelativeLayout
android:id="@+id/loader_none"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="已显示全部"
android:textSize="18sp" />
</RelativeLayout>
</RelativeLayout>
<!-- ListView底部加载更多按钮 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:padding="10dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/gray" />
<!-- 正在加载 -->
<RelativeLayout
android:id="@+id/loader_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="正在加载..."
android:textSize="18sp" />
</RelativeLayout>
<!-- 加载更多 -->
<RelativeLayout
android:id="@+id/loader_load"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="点此加载更多"
android:textSize="18sp" />
</RelativeLayout>
<!-- 已显示全部 -->
<RelativeLayout
android:id="@+id/loader_none"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="已显示全部"
android:textSize="18sp" />
</RelativeLayout>
</RelativeLayout>
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;
}
}
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<ListItem> items;
private Context context;
private LayoutInflater inflater;
public DemoAdapter(Context context, List<ListItem> 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;
}
}
private List<ListItem> items;
private Context context;
private LayoutInflater inflater;
public DemoAdapter(Context context, List<ListItem> 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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
activity入口定义
public class PagerListViewActivity extends Activity {
private PagerListView pagerListView;
private DemoAdapter adapter;
private List<ListItem> list = new Vector<ListItem>();
@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<pageSize;i++){
ListItem item = new ListItem();
item.setTitle("标题"+i);
item.setContent("内容"+i);
list.add(item);
}
pagerListView.loadComplete();
}
@Override
public void handleResult(String result) {
}
});
}
});
}
}
private PagerListView pagerListView;
private DemoAdapter adapter;
private List<ListItem> list = new Vector<ListItem>();
@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<pageSize;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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<com.example.fxgandroid.pagerlistview.PagerListView
android:id="@+id/pagerlistview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.fxgandroid.pagerlistview.PagerListView>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<com.example.fxgandroid.pagerlistview.PagerListView
android:id="@+id/pagerlistview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.fxgandroid.pagerlistview.PagerListView>
</LinearLayout>
运行效果
0 0
- Android自定义ListView实现上滑分页
- Android自定义ListView实现分页加载
- 自定义ListView实现上拉分页加载更多数据
- Android中ListView的分页--自定义ListView
- Android 自定义ListView 实现下拉刷新 上拉加载功能
- Android ListView 分页加载实现
- Android自定义控件(一) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- Android自定义控件(二) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- ListView分页功能(2) 自定义View实现分页功能
- Android 自定义ListView实现底部分页刷新与顶部下拉刷新
- Android 自定义ListView实现底部分页刷新与顶部下拉刷新
- Android 自定义ListView实现底部分页刷新与顶部下拉刷新 .
- Android 自定义ListView实现底部分页刷新与顶部下拉刷新,androidlistview
- Android复杂自定义Listview实现
- android ListView自定义适配器实现
- android 自定义ListView实现下拉刷新、分页加载、点击事件——自定义控件学习(七)
- Android listview怎么实现滚动分页
- ListView 实现像Android Market那样分页
- 懒加载异常的解决办法
- iOS判断UIView是否显示在屏幕上
- 一个信号量与定时器的例子(Golang)
- webUI——jBox快速入门
- html+css实现3D旋转图片展示
- Android自定义ListView实现上滑分页
- 【基础篇系列5】java核心(二)
- C#中的委托和事件
- C Language Study - a dangerous function - getchar()
- HDU 2829 Lawrence 斜率优化DP
- MySQL数据库诊断:InnoDB关机问题
- 如何让你的App图标杀出重围?
- /sys/class/gpio
- HOARE_QUICKSORT 算法导论上提供的Hoare的原版PARTITION