ListView和AsyncTask结合实现下拉刷新

下面就ListView和AsyncTask如何实现数据加载和下拉刷新和上拉加载数据的具体代码,,代码注释很详细:

源码下载源码下载

自定义MyListView :

package cn.zxw.pull.refresh.view;import java.text.SimpleDateFormat;import java.util.logging.SimpleFormatter;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ImageView;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;import cn.zxw.pull.refresh.R;public class MyListView extends ListView implements OnScrollListener {// 加载数据的接口public interface OnListViewLoadDataListener {public void onLoadNewData();// 加载更多数据public void onLoadMoreData();}private OnListViewLoadDataListener onListViewLoadDataListener;public void setOnListViewLoadDataListener(OnListViewLoadDataListener onListViewLoadDataListener) {this.onListViewLoadDataListener = onListViewLoadDataListener;}private static final String TAG = "MyListView";private View header;private ImageView iv_arrow;private ProgressBar pb;private TextView tv_state;private TextView tv_time;private int height;enum HeaderState {PULL_DOWN_REFRESH, // 下拉刷新RELEASE_REFRESH, // 释放刷新REFRESHING// 正在刷新}// 设置默认状态private HeaderState state = HeaderState.PULL_DOWN_REFRESH;// ListView头文字的信息private String[] stateInfos = new String[] { "下拉刷新", "释放刷新", "正在刷新" };public MyListView(Context context) {super(context);}public MyListView(Context context, AttributeSet attrs) {super(context, attrs);initHead();initFooter();setOnScrollListener(this);}/** * 初始化footer */private void initFooter() {footer = View.inflate(getContext(), R.layout.footer, null);footer.measure(0, 0);footerHeight = footer.getMeasuredHeight();footer.setPadding(0, -footerHeight, 0, 0);addFooterView(footer);}/** * 初始化listview的头部 */private void initHead() {header = View.inflate(getContext(), R.layout.header, null);iv_arrow = (ImageView) header.findViewById(R.id.iv_arrow);pb = (ProgressBar) header.findViewById(R.id.pb);tv_state = (TextView) header.findViewById(R.id.tv_state);tv_time = (TextView) header.findViewById(R.id.tv_time);pb.setVisibility(View.INVISIBLE);// 隐藏pbaddHeaderView(header);// 添加header,然后要隐藏header//int height = header.getHeight(); 如果一个控件没有显示 是无法获取宽高 layoutheader.measure(0, 0);//Android中控件的位置必须先测量height = header.getMeasuredHeight();//获取控件的高度header.setPadding(0, -height, 0, 0);// 隐藏控件,即是将控件设置在屏幕顶部之外}public MyListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}private boolean isLoadingData = false;// 是否加载更多数据// 滑动状态改变// 闲置和飞行状态 listview必须是已经显示到最后下处理@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {int lastVisiblePosition = getLastVisiblePosition();// 获取listview最后显示的下标int count = getAdapter().getCount();// 闲置状态和飞行状态 还必须是ListView已经显示到最后 没有在加载数据if ((scrollState == OnScrollListener.SCROLL_STATE_IDLE || scrollState == OnScrollListener.SCROLL_STATE_FLING)&& lastVisiblePosition == count – 1 && !isLoadingData) {isLoadingData = true;footer.setPadding(0, 0, 0, 0);// 脚其实还是没有显示setSelection(count);if (onListViewLoadDataListener != null) {onListViewLoadDataListener.onLoadMoreData();}}switch (scrollState) {case OnScrollListener.SCROLL_STATE_IDLE:// 闲置break;case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:// 滑动break;case OnScrollListener.SCROLL_STATE_FLING:// 飞行break;default:break;}}/** * firstVisibleItem 屏幕上显示的第一个条目的下标 *visibleItemCount 屏幕上显示的条目总数 * totalItemCount 条目总数 */private int firstVisibleItem;// 记录第一个条目位置@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {this.firstVisibleItem = firstVisibleItem;Log.i(TAG, "firstVisibleItem:" + firstVisibleItem);}private int startY;private int footerHeight;private View footer;// 滑动改变header@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "ACTION_DOWN");startY = (int) ev.getY();break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "ACTION_MOVE");// 显示的是第一个条目if (firstVisibleItem == 0 && state != HeaderState.REFRESHING) {int moveY = (int) ev.getY();int disY = moveY – startY;// 控制header的显示int top = -height + disY;if (top > 0 && state == HeaderState.PULL_DOWN_REFRESH) {// 原来是下拉刷新// 现在置为释放刷新state = HeaderState.RELEASE_REFRESH;RotateAnimation animation = getRotateAnimation1();iv_arrow.setAnimation(animation);tv_state.setText(stateInfos[1]);} else if (top <= 0 && state == HeaderState.RELEASE_REFRESH) {// 原来是释放刷新 现在变为下拉刷新state = HeaderState.PULL_DOWN_REFRESH;RotateAnimation animation = getRotateAnimation2();iv_arrow.setAnimation(animation);tv_state.setText(stateInfos[2]);}header.setPadding(0, top, 0, 0);}break;case MotionEvent.ACTION_UP:Log.i(TAG, "ACTION_UP");// 用户松开手指:1 下拉刷新 2 释放刷新if (state == HeaderState.PULL_DOWN_REFRESH) {// 把头直接隐藏header.setPadding(0, -height, 0, 0);} else if (state == HeaderState.RELEASE_REFRESH) {// 把头显示在第一行 作为一个正常的显示// 把头的状态进行改变header.setPadding(0, 0, 0, 0);state = HeaderState.REFRESHING;iv_arrow.clearAnimation();// 清除动画iv_arrow.setVisibility(View.INVISIBLE);// 箭头无法隐藏:iv_arrow有动画pb.setVisibility(View.VISIBLE);tv_state.setText(stateInfos[2]);// 通知activity加载数据if (onListViewLoadDataListener != null) {onListViewLoadDataListener.onLoadNewData();}}break;default:break;}return super.onTouchEvent(ev);}public RotateAnimation getRotateAnimation1() {RotateAnimation rotateAnimation = new RotateAnimation(0, -180,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);rotateAnimation.setDuration(200);rotateAnimation.setFillAfter(true);return rotateAnimation;}public RotateAnimation getRotateAnimation2() {RotateAnimation rotateAnimation = new RotateAnimation(-180, -360,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);rotateAnimation.setDuration(200);rotateAnimation.setFillAfter(true);return rotateAnimation;}// 隐藏头// 1.状态改为下拉刷新// 2.隐藏进度条 显示箭头 修改文字// 3.刷新的事件// 4.header设置paddingpublic void hideHeader() {state = HeaderState.PULL_DOWN_REFRESH;pb.setVisibility(View.INVISIBLE);iv_arrow.setVisibility(View.VISIBLE);tv_state.setText(stateInfos[0]);long mills = System.currentTimeMillis();SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");String dateStr = format.format(mills);tv_time.setText("上次刷新的时间为:" + dateStr);header.setPadding(0, -height, 0, 0);}// 隐藏footerpublic void hideFooter() {footer.setPadding(0, -footerHeight, 0, 0);isLoadingData = false;}}MainActivity:package cn.zxw.pull.refresh;import java.util.ArrayList;import java.util.List;import cn.zxw.pull.refresh.view.MyListView;import cn.zxw.pull.refresh.view.MyListView.OnListViewLoadDataListener;import android.os.AsyncTask;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.app.Activity;import android.widget.ArrayAdapter;public class MainActivity extends Activity implementsOnListViewLoadDataListener {protected static final int SUCCESS_LOAD_NEW_DATA = 0;protected static final int SUCCESS_LOAD_MORE_DATA =1;private MyListView lv;private ArrayAdapter<String> adapter;private List<String> objects;Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case SUCCESS_LOAD_NEW_DATA:String data = (String) msg.obj;objects.add(0,data);adapter.notifyDataSetChanged();lv.hideHeader();break;case SUCCESS_LOAD_MORE_DATA:List<String> list = (List<String>) msg.obj;objects.addAll(list);adapter.notifyDataSetChanged();lv.hideFooter();break;default:break;}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lv = (MyListView) findViewById(R.id.lv);// 值的初始化objects = new ArrayList<String>();for (int i = 0; i < 13; i++) {objects.add("初始化的数据" + i);}adapter = new ArrayAdapter<String>(getApplication(),android.R.layout.simple_list_item_1, android.R.id.text1,objects);lv.setAdapter(adapter);lv.setOnListViewLoadDataListener(this);}@Overridepublic void onLoadNewData() {new Thread() {public void run() {SystemClock.sleep(3000);String data = "加载的数据";Message msg = Message.obtain();msg.what = SUCCESS_LOAD_NEW_DATA;msg.obj = data;handler.sendMessage(msg);};}.start();}@Overridepublic void onLoadMoreData() {new MyAsyncTask().execute("");}//Params 参数:一般都是要执行下载的路径 String Progress 进度条的值 Integer, Result 结果 Bitmap String List<String> private class MyAsyncTask extends AsyncTask<String , Integer, List<String>>{//准备@Overrideprotected void onPreExecute() {super.onPreExecute();}//执行后台的耗时操作@Overrideprotected List<String> doInBackground(String… params) {SystemClock.sleep(3000);List<String> list=new ArrayList<String>();for (int i = 0; i <5; i++) {list.add("加载更多数据"+i);}return list;}//下载完成后@Overrideprotected void onPostExecute(List<String> result) {super.onPostExecute(result);objects.addAll(result);adapter.notifyDataSetChanged();lv.hideFooter();}//必须是有另外一个方法的调用才会调用该方法//publishProgress() 该方法一般都是在doInBackground(String… params)里面调用@Overrideprotected void onProgressUpdate(Integer… values) {super.onProgressUpdate(values);}}}如果想详细知道AsyncTask可以参考scott’s的博客

哪怕前方的路会充满坎坷,但为梦想而拼搏的人会永不言败

ListView和AsyncTask结合实现下拉刷新

相关文章:

你感兴趣的文章:

标签云: