首先还是看看结构吧
MainActivity
package com.example.pagerefreshlistview;
import java.util.List;
import com.example.refreshlist.RefreshListView;
import android.os.AsyncTask;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.support.v4.app.NavUtils;
@SuppressLint("ParserError")
public class MainActivity extends Activity implements
RefreshListView.IOnRefreshListener, RefreshListView.IOnLoadMoreListener{
private static int PAGEINDEX=1;//当前页
private final static int PAGENUMBER=10;//一页显示条数
private int total=30;//总条数
private int isDrop=0;//1.下拉刷新,2.点击查看更多分页
private RefreshListView refreshListView;
private List<Users> list;
private MyAdapter adapter;
private MyAsyncTask myAsyncTask;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
refreshListView=(RefreshListView)findViewById(R.id.listView1);
refreshListView.setOnRefreshListener(this);//刷新事件
refreshListView.setOnLoadMoreListener(this);//分页加载事件
LoadData();
}
//加载数据
public void LoadData(){
myAsyncTask=new MyAsyncTask("", PAGEINDEX, PAGENUMBER);
myAsyncTask.execute();
}
public class MyAsyncTask extends NetAsyncTask{
public MyAsyncTask(String url, int pageindex, int pagenumber) {
super(url, pageindex, pagenumber);
// TODO Auto-generated constructor stub
}
@Override
protected void onPostExecute(List<Users> result) {
Log.v("result", "result----------");
if(result!=null&&result.size()>0){
if (PAGEINDEX == 1) {//如果是第一页,直接赋值
list = result;
if (total > PAGENUMBER) {
refreshListView.onLoadMoreComplete(0);//如果需要分页,显示“查看更多”
}else{
refreshListView.onLoadMoreComplete(3);//否则不显示
}
} else{
list.addAll(result);//如果不是第一页,将新结果添加到list
}
if(isDrop==0){//第一次加载数据
adapter=new MyAdapter(MainActivity.this,list);
refreshListView.setAdapter(adapter);
refreshListView.setDividerHeight(2);//分隔线的高度
}else if(isDrop==1||isDrop==2){
adapter.refreshData(list);//刷新数据列表
refreshListView.onRefreshComplete();
if (isDrop == 2) {//如果分页,判断数据是否加载完成
if (PAGEINDEX * PAGENUMBER >= total) {
refreshListView.onLoadMoreComplete(2);//加载已完成
} else {
refreshListView.onLoadMoreComplete(0);//未完成,显示“查看更多”
}
}
}
}
}
}
public class MyAdapter extends BaseAdapter{
List<Users> data;
public MyAdapter(Context context,List<Users> data){
this.data=data;
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
//重新加载数据
public void refreshData(List<Users> data) {
this.data = data;
notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView==null){
convertView=getLayoutInflater().inflate(R.layout.lv_item, null);
holder=new ViewHolder();
holder.uidView=(TextView)convertView.findViewById(R.id.tv_uid);
holder.unameView=(TextView)convertView.findViewById(R.id.tv_uname);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
holder.uidView.setText(data.get(position).getUserID());
holder.unameView.setText(data.get(position).getUserName());
return convertView;
}
}
//下拉刷新
public void OnRefresh() {
Log.v("OnRefresh", "OnRefresh=====================");
PAGEINDEX = 1;//刷新第一页
isDrop = 1;//设置操作
RefreshDataAsynTask mRefreshAsynTask = new RefreshDataAsynTask();
mRefreshAsynTask.execute();
}
public class RefreshDataAsynTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LoadData();//获取数据
return null;
}
}
//点击查看更多时,分页
public void OnLoadMore() {
Log.v("OnLoadMore", "OnLoadMore_____________");
isDrop = 2;//设置操作
PAGEINDEX++;//页数加1
LoadMoreDataAsynTask mLoadMoreAsynTask = new LoadMoreDataAsynTask();
mLoadMoreAsynTask.execute();
}
public class LoadMoreDataAsynTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LoadData();//获取数据
return null;
}
}
}
NetAsyncTask
package com.example.pagerefreshlistview;
import java.util.List;
import android.annotation.SuppressLint;
import android.os.AsyncTask;
@SuppressLint("ParserError")
public class NetAsyncTask extends AsyncTask<Void, Integer, List<Users>>{
private String url;//请求url
private int pageindex;
private int pagenumber;
private NetServer netServer;
public NetAsyncTask(String url,int pageindex,int pagenumber){
this.url=url;
this.pageindex=pageindex;
this.pagenumber=pagenumber;
netServer=new NetServer();
}
@Override
protected List<Users> doInBackground(Void... params) {
// TODO Auto-generated method stub
return netServer.getList(pageindex, pagenumber);
}
}
NetServer
package com.example.pagerefreshlistview;
import java.util.ArrayList;
import java.util.List;
public class NetServer {
private List<Users> list;
//初始化数据
public List<Users> getList(int pageindex,int pagenumber){
list=new ArrayList<Users>();
Users users;
int start=1;
if(pageindex!=1){
start=(pageindex-1)*pagenumber;
}
for (int i = start; i <= pageindex*pagenumber; i++) {
users=new Users();
users.setUserID("UserID "+i);
users.setUserName("UserName "+i);
list.add(users);
}
return list;
}
}
Users
package com.example.pagerefreshlistview;
/*
* 实体类
* */
public class Users {
private String UserID;
private String userName;
public String getUserID() {
return UserID;
}
public void setUserID(String userID) {
UserID = userID;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
ViewHolder
package com.example.pagerefreshlistview;
import android.widget.TextView;
public class ViewHolder {
public TextView uidView;
public TextView unameView;
}
RefreshListView
package com.example.refreshlist;
import java.util.Date;
import com.example.pagerefreshlistview.R;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
public class RefreshListView extends ListView implements OnScrollListener, OnClickListener{
public interface IListViewState
{
int LVS_NORMAL = 0; // 普通状态
int LVS_PULL_REFRESH = 1; // 下拉刷新状态
int LVS_RELEASE_REFRESH = 2; // 松开刷新状态
int LVS_LOADING = 3; // 加载状态
}
public interface IOnRefreshListener
{
void OnRefresh();
}
private View mHeadView;
private TextView mRefreshTextview;
private TextView mLastUpdateTextView;
private ImageView mArrowImageView;
private ProgressBar mHeadProgressBar;
private int mHeadContentWidth;
private int mHeadContentHeight;
private IOnRefreshListener mOnRefreshListener; // 头部刷新监听器
// 用于保证startY的值在一个完整的touch事件中只被记录一次
private boolean mIsRecord = false;
// 标记的Y坐标值
private int mStartY = 0;
// 当前视图能看到的第一个项的索引
private int mFirstItemIndex = -1;
// MOVE时保存的Y坐标值
private int mMoveY = 0;
// LISTVIEW状态
private int mViewState = IListViewState.LVS_NORMAL;
private final static int RATIO = 2;
private RotateAnimation animation;
private RotateAnimation reverseAnimation;
private boolean mBack = false;
public RefreshListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void setOnRefreshListener(IOnRefreshListener listener)
{
mOnRefreshListener = listener;
}
private void onRefresh()
{
if (mOnRefreshListener != null)
{
mOnRefreshListener.OnRefresh();
}
}
public void onRefreshComplete()
{
mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
mLastUpdateTextView.setText("最近更新:" + new Date().toLocaleString());
switchViewState(IListViewState.LVS_NORMAL);
}
private void init(Context context)
{
initHeadView(context);
initLoadMoreView(context);
setOnScrollListener(this);
}
// 初始化headview试图
private void initHeadView(Context context)
{
mHeadView = LayoutInflater.from(context).inflate(R.layout.listview_head, null);
mArrowImageView = (ImageView) mHeadView.findViewById(R.id.head_arrowImageView);
mArrowImageView.setMinimumWidth(60);
mHeadProgressBar= (ProgressBar) mHeadView.findViewById(R.id.head_progressBar);
mRefreshTextview = (TextView) mHeadView.findViewById(R.id.head_tipsTextView);
mLastUpdateTextView = (TextView) mHeadView.findViewById(R.id.head_lastUpdatedTextView);
measureView(mHeadView);
mHeadContentHeight = mHeadView.getMeasuredHeight();
mHeadContentWidth = mHeadView.getMeasuredWidth();
mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
mHeadView.invalidate();
addHeaderView(mHeadView, null, false);
animation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(250);
animation.setFillAfter(true);
reverseAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reverseAnimation.setInterpolator(new LinearInterpolator());
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);
}
// 初始化footview试图
private void initLoadMoreView(Context context)
{
mFootView= LayoutInflater.from(context).inflate(R.layout.loadmore, null);
mLoadMoreView = mFootView.findViewById(R.id.load_more_view);
mLoadMoreTextView = (TextView) mFootView.findViewById(R.id.load_more_tv);
mLoadingView = mFootView.findViewById(R.id.loading_layout);
mLoadMoreView.setOnClickListener(this);
addFooterView(mFootView);
}
// 此方法直接照搬自网络上的一个下拉刷新的demo,计算headView的width以及height
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
public void onScroll(AbsListView arg0, int firstVisiableItem, int visibleItemCount, int totalItemCount) {
mFirstItemIndex = firstVisiableItem;
}
public void onScrollStateChanged(AbsListView arg0, int arg1) {
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
if (mOnRefreshListener != null)
{
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
doActionDown(ev);
break;
case MotionEvent.ACTION_MOVE:
doActionMove(ev);
break;
case MotionEvent.ACTION_UP:
doActionUp(ev);
break;
default:
break;
}
}
return super.onTouchEvent(ev);
}
private void doActionDown(MotionEvent ev)
{
if(mIsRecord == false && mFirstItemIndex == 0)
{
mStartY = (int) ev.getY();
mIsRecord = true;
}
}
private void doActionMove(MotionEvent ev)
{
mMoveY = (int) ev.getY();
if(mIsRecord == false && mFirstItemIndex == 0)
{
mStartY = (int) ev.getY();
mIsRecord = true;
}
if (mIsRecord == false || mViewState == IListViewState.LVS_LOADING)
{
return ;
}
int offset = (mMoveY - mStartY) / RATIO;
switch(mViewState)
{
case IListViewState.LVS_NORMAL:
{
if (offset > 0)
{
mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
switchViewState(IListViewState.LVS_PULL_REFRESH);
}
}
break;
case IListViewState.LVS_PULL_REFRESH:
{
setSelection(0);
mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
if (offset < 0)
{
switchViewState(IListViewState.LVS_NORMAL);
}else if (offset > mHeadContentHeight)
{
switchViewState(IListViewState.LVS_RELEASE_REFRESH);
}
}
break;
case IListViewState.LVS_RELEASE_REFRESH:
{
setSelection(0);
mHeadView.setPadding(0, offset - mHeadContentHeight, 0, 0);
if (offset >= 0 && offset <= mHeadContentHeight)
{
mBack = true;
switchViewState(IListViewState.LVS_PULL_REFRESH);
}else if (offset < 0)
{
switchViewState(IListViewState.LVS_NORMAL);
}else{
}
}
break;
default:
return;
};
}
private void doActionUp(MotionEvent ev)
{
mIsRecord = false;
mBack = false;
if (mViewState == IListViewState.LVS_LOADING)
{
return ;
}
switch(mViewState)
{
case IListViewState.LVS_NORMAL:
break;
case IListViewState.LVS_PULL_REFRESH:
mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
switchViewState(IListViewState.LVS_NORMAL);
break;
case IListViewState.LVS_RELEASE_REFRESH:
mHeadView.setPadding(0, 0, 0, 0);
switchViewState(IListViewState.LVS_LOADING);
onRefresh();
break;
}
}
// 切换headview视图
private void switchViewState(int state)
{
switch(state)
{
case IListViewState.LVS_NORMAL:
{
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_NORMAL");
mArrowImageView.clearAnimation();
mArrowImageView.setImageResource(R.drawable.arrow);
}
break;
case IListViewState.LVS_PULL_REFRESH:
{
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_PULL_REFRESH");
mHeadProgressBar.setVisibility(View.GONE);
mArrowImageView.setVisibility(View.VISIBLE);
mRefreshTextview.setText("下拉可以刷新");
mArrowImageView.clearAnimation();
// 是由RELEASE_To_REFRESH状态转变来的
if (mBack)
{
mBack = false;
mArrowImageView.clearAnimation();
mArrowImageView.startAnimation(reverseAnimation);
}
}
break;
case IListViewState.LVS_RELEASE_REFRESH:
{
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_RELEASE_REFRESH");
mHeadProgressBar.setVisibility(View.GONE);
mArrowImageView.setVisibility(View.VISIBLE);
mRefreshTextview.setText("松开获取更多");
mArrowImageView.clearAnimation();
mArrowImageView.startAnimation(animation);
}
break;
case IListViewState.LVS_LOADING:
{
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
mHeadProgressBar.setVisibility(View.VISIBLE);
mArrowImageView.clearAnimation();
mArrowImageView.setVisibility(View.GONE);
mRefreshTextview.setText("载入中...");
}
break;
default:
return;
}
mViewState = state;
}
private View mFootView;
private View mLoadMoreView;
private TextView mLoadMoreTextView;
private View mLoadingView;
private IOnLoadMoreListener mLoadMoreListener; // 加载更多监听器
private int mLoadMoreState = IListViewState.LVS_NORMAL;
public interface ILoadMoreViewState
{
int LMVS_NORMAL= 0; // 普通状态
int LMVS_LOADING = 1; // 加载状态
int LMVS_OVER = 2; // 结束状态
int LMVS_END = 3; // 没有数据
}
public interface IOnLoadMoreListener
{
void OnLoadMore();
}
public void setOnLoadMoreListener(IOnLoadMoreListener listener)
{
mLoadMoreListener = listener;
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId())
{
case R.id.load_more_view:
{
if (mLoadMoreListener != null && mLoadMoreState == IListViewState.LVS_NORMAL)
{
updateLoadMoreViewState(ILoadMoreViewState.LMVS_LOADING);
mLoadMoreListener.OnLoadMore();
}
}
break;
}
}
/*
* flag 当前状态
* 0.普通状态,显示:查看更多
* 1.加载状态,显示:正在加载
* 2.结束状态,数据全部加载,显示:数据加载完毕
* 3.没有数据,当没有数据时,隐藏该项
* */
public void onLoadMoreComplete(int flag)
{
updateLoadMoreViewState(flag);
}
// 更新footview视图
private void updateLoadMoreViewState(int state)
{
switch(state)
{
case ILoadMoreViewState.LMVS_NORMAL:
mLoadingView.setVisibility(View.GONE);
mLoadMoreTextView.setVisibility(View.VISIBLE);
mLoadMoreTextView.setText("查看更多");
break;
case ILoadMoreViewState.LMVS_LOADING:
mLoadingView.setVisibility(View.VISIBLE);
mLoadMoreTextView.setVisibility(View.GONE);
break;
case ILoadMoreViewState.LMVS_OVER:
mLoadingView.setVisibility(View.GONE);
mLoadMoreTextView.setVisibility(View.VISIBLE);
mLoadMoreTextView.setText("数据加载完毕!");
break;
case ILoadMoreViewState.LMVS_END:
mLoadingView.setVisibility(View.GONE);
mLoadMoreTextView.setVisibility(View.GONE);
mLoadMoreTextView.setText("");
break;
default:
break;
}
mLoadMoreState = state;
}
public void removeFootView()
{
removeFooterView(mFootView);
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.refreshlist.RefreshListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:fadingEdge="none"
android:divider="@drawable/table_line"
android:footerDividersEnabled="false" />
</RelativeLayout>
listview_head.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- ListView的头部 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/cell_bg" >
<!-- 内容 -->
<RelativeLayout
android:id="@+id/head_contentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- 箭头图像、进度条 -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp" >
<!-- 箭头 -->
<ImageView
android:id="@+id/head_arrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/arrow" />
<!-- 进度条 -->
<ProgressBar
android:id="@+id/head_progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
<!-- 提示、最近更新 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical" >
<!-- 提示 -->
<TextView
android:id="@+id/head_tipsTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉可以刷新"
android:textColor="@color/cell_title"
android:textSize="20sp" />
<!-- 最近更新 -->
<TextView
android:id="@+id/head_lastUpdatedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上次更新"
android:textColor="@color/cell_title"
android:textSize="10sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1px"
android:layout_alignParentBottom="true"
android:background="@color/white" >
</View>
</RelativeLayout>
</LinearLayout>
loadmore.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/load_more_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/load_more_selector"
android:clickable="true"
android:gravity="center"
android:minHeight="50dp" >
<TextView
android:id="@+id/load_more_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text=""
android:textColor="@color/cell_title"
android:textSize="20sp" />
<LinearLayout
android:id="@+id/loading_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone" >
<ProgressBar
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#333333"
android:text="加载中..."
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
lv_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tv_uid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="21dp"
android:layout_marginTop="16dp"
android:text="TextView" />
<TextView
android:id="@+id/tv_uname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/tv_uid"
android:layout_alignBottom="@+id/tv_uid"
android:layout_alignParentRight="true"
android:layout_marginRight="28dp"
android:text="TextView" />
</RelativeLayout>
load_more_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/cell_gl" />
</shape>
load_more_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/load_more_selected" />
<item android:state_focused="true" android:drawable="@drawable/load_more_selected" />
</selector>
arrow.png
ic_action_search.png
table_line.png
最后看效果图