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>

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<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>

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) {

}
});
}
});
}
}

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>

运行效果

   

0 0
原创粉丝点击