Android ListView列表 刷新和加载更多

原文地址:http://blog.csdn.net/trbbadboy/article/details/8565679#comments


上下拉实现刷新和加载更多的ListView,如下:

  1. package com.sin.android.ui;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.Gravity;  
  6. import android.view.MotionEvent;  
  7. import android.view.View;  
  8. import android.widget.AbsListView;  
  9. import android.widget.AbsListView.OnScrollListener;  
  10. import android.widget.LinearLayout;  
  11. import android.widget.ListView;  
  12. import android.widget.ProgressBar;  
  13. import android.widget.TextView;  
  14.   
  15.   
  16. /** 
  17.  * 动态刷新和加载数据ListView 
  18.  * @author RobinTang 
  19.  * 
  20.  */  
  21. public class DynamicListView extends ListView implements OnScrollListener {  
  22.   
  23.     /** 
  24.      * 监听器 
  25.      * 监听控件的刷新或者加载更多事件 
  26.      * 所有的条目事件都会有一个偏移量,也就是position应该减1才是你适配器中的条目 
  27.      * @author RobinTang 
  28.      * 
  29.      */  
  30.     public interface DynamicListViewListener {  
  31.         /** 
  32.          *  
  33.          * @param dynamicListView 
  34.          * @param isRefresh 为true的时候代表的是刷新,为false的时候代表的是加载更多 
  35.          * @return true:刷新或者加载更多动作完成,刷新或者加载更多的动画自动消失 false:刷新或者加载更多为完成,需要在数据加载完成之后去调用控件的doneRefresh()或者doneMore()方法  
  36.          */  
  37.         public boolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh);  
  38.     }  
  39.       
  40.   
  41.     /** 
  42.      * 状态控件(StatusView,列表头上和底端的)的状态枚举 
  43.      * @author RobinTang 
  44.      * 
  45.      */  
  46.     enum RefreshStatus {  
  47.         none, normal, willrefresh, refreshing  
  48.     }  
  49.       
  50.     /** 
  51.      * 状态控件 
  52.      * @author RobinTang 
  53.      * 
  54.      */  
  55.     class StatusView extends LinearLayout {  
  56.         public int height;  
  57.         public int width;  
  58.         private ProgressBar progressBar = null;  
  59.         private TextView textView = null;  
  60.         private RefreshStatus refreshStatus = RefreshStatus.none;  
  61.         private String normalString = "下拉刷新";  
  62.         private String willrefreshString = "松开刷新";  
  63.         private String refreshingString = "正在刷新";  
  64.   
  65.         public StatusView(Context context, AttributeSet attrs) {  
  66.             super(context, attrs);  
  67.             initThis(context);  
  68.         }  
  69.   
  70.         public StatusView(Context context) {  
  71.             super(context);  
  72.             initThis(context);  
  73.         }  
  74.   
  75.         private void initThis(Context context) {  
  76.             this.setOrientation(LinearLayout.HORIZONTAL);  
  77.             this.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);  
  78.   
  79.             progressBar = new ProgressBar(context);  
  80.             progressBar.setLayoutParams(new LinearLayout.LayoutParams(3030));  
  81.             textView = new TextView(context);  
  82.             textView.setPadding(5000);  
  83.   
  84.             this.addView(progressBar);  
  85.             this.addView(textView);  
  86.   
  87.             int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  88.             int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  89.             this.measure(w, h);  
  90.   
  91.             height = this.getMeasuredHeight();  
  92.             width = this.getMeasuredWidth();  
  93.   
  94.             this.setRefreshStatus(RefreshStatus.normal);  
  95.         }  
  96.   
  97.         public RefreshStatus getRefreshStatus() {  
  98.             return refreshStatus;  
  99.         }  
  100.   
  101.         public void setRefreshStatus(RefreshStatus refreshStatus) {  
  102.             if (this.refreshStatus != refreshStatus) {  
  103.                 this.refreshStatus = refreshStatus;  
  104.                 if(refreshStatus == RefreshStatus.refreshing){  
  105.                     this.progressBar.setVisibility(View.VISIBLE);  
  106.                 }  
  107.                 else{  
  108.                     this.progressBar.setVisibility(View.GONE);  
  109.                 }  
  110.                 refreshStatusString();  
  111.                 this.invalidate();  
  112.             }  
  113.         }  
  114.   
  115.         private void refreshStatusString() {  
  116.             switch (refreshStatus) {  
  117.             case normal:  
  118.                 textView.setText(normalString);  
  119.                 progressBar.setProgress(0);  
  120.                 break;  
  121.             case willrefresh:  
  122.                 textView.setText(willrefreshString);  
  123.                 break;  
  124.             case refreshing:  
  125.                 textView.setText(refreshingString);  
  126.                 break;  
  127.             default:  
  128.                 break;  
  129.             }  
  130.         }  
  131.           
  132.         /** 
  133.          * 设置状态字符串 
  134.          * @param normalString  平时的字符串 
  135.          * @param willrefreshString 松开后刷新(或加载)的字符串 
  136.          * @param refreshingString  正在刷新(或加载)的字符串 
  137.          */  
  138.         public void setStatusStrings(String normalString, String willrefreshString, String refreshingString){  
  139.             this.normalString = normalString;  
  140.             this.willrefreshString = willrefreshString;  
  141.             this.refreshingString = refreshingString;  
  142.             this.refreshStatusString();  
  143.         }  
  144.     }  
  145.   
  146.     private StatusView refreshView;  
  147.     private StatusView moreView;  
  148.     private int itemFlag = -1;  
  149.     private boolean isRecorded = false;  
  150.     private int downY = -1;  
  151.     private final float minTimesToRefresh = 1.5f;  
  152.     private final static int ITEM_FLAG_FIRST = 1;  
  153.     private final static int ITEM_FLAG_NONE = 0;  
  154.     private final static int ITEM_FLAG_LAST = -1;  
  155.       
  156.     // 两个监听器  
  157.     private DynamicListViewListener onRefreshListener;  
  158.     private DynamicListViewListener onMoreListener;  
  159.     // 滚动到低端的时候是否自动加载更多  
  160.     private boolean doMoreWhenBottom = false;  
  161.       
  162.   
  163.     public DynamicListView(Context context, AttributeSet attrs, int defStyle) {  
  164.         super(context, attrs, defStyle);  
  165.         initThis(context);  
  166.     }  
  167.   
  168.     public DynamicListView(Context context, AttributeSet attrs) {  
  169.         super(context, attrs);  
  170.         initThis(context);  
  171.     }  
  172.   
  173.     public DynamicListView(Context context) {  
  174.         super(context);  
  175.         initThis(context);  
  176.     }  
  177.   
  178.     private void initThis(Context context) {  
  179.         refreshView = new StatusView(context);  
  180.         moreView = new StatusView(context);  
  181.         refreshView.setStatusStrings("继续下拉刷新数据...""松开之后刷新数据...""正在刷新数据...");  
  182.         moreView.setStatusStrings("继续上拉加载数据...""松开之后加载数据...""正在加载数据...");  
  183.         this.addHeaderView(refreshView, nullfalse);  
  184.         this.addFooterView(moreView, nullfalse);  
  185.         this.setOnScrollListener(this);  
  186.         doneRefresh();  
  187.         doneMore();  
  188.     }  
  189.   
  190.       
  191.     // 监听器操作  
  192.     public DynamicListViewListener getOnRefreshListener() {  
  193.         return onRefreshListener;  
  194.     }  
  195.   
  196.     public void setOnRefreshListener(DynamicListViewListener onRefreshListener) {  
  197.         this.onRefreshListener = onRefreshListener;  
  198.     }  
  199.   
  200.     public DynamicListViewListener getOnMoreListener() {  
  201.         return onMoreListener;  
  202.     }  
  203.   
  204.     public void setOnMoreListener(DynamicListViewListener onMoreListener) {  
  205.         this.onMoreListener = onMoreListener;  
  206.     }  
  207.   
  208.     // 设置  
  209.     public boolean isDoMoreWhenBottom() {  
  210.         return doMoreWhenBottom;  
  211.     }  
  212.   
  213.     public void setDoMoreWhenBottom(boolean doMoreWhenBottom) {  
  214.         this.doMoreWhenBottom = doMoreWhenBottom;  
  215.     }  
  216.   
  217.     @Override  
  218.     public void onScroll(AbsListView l, int t, int oldl, int count) {  
  219.         // log("%d %d %d", t, oldl, count);  
  220.         if (t == 0)  
  221.             itemFlag = ITEM_FLAG_FIRST;  
  222.         else if ((t + oldl) == count){  
  223.             itemFlag = ITEM_FLAG_LAST;  
  224.             if(doMoreWhenBottom && onMoreListener != null && moreView.getRefreshStatus() != RefreshStatus.refreshing){  
  225.                     doMore();  
  226.             }  
  227.         }  
  228.         else {  
  229.             itemFlag = ITEM_FLAG_NONE;  
  230. //          isRecorded = false;  
  231.         }  
  232.     }  
  233.   
  234.     @Override  
  235.     public void onScrollStateChanged(AbsListView arg0, int arg1) {  
  236.   
  237.     }  
  238.   
  239.     @Override  
  240.     public boolean onTouchEvent(MotionEvent ev) {  
  241.         switch (ev.getAction()) {  
  242.         case MotionEvent.ACTION_DOWN:  
  243.             if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal || itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {  
  244.                 downY = (int) ev.getY(0);  
  245.                 isRecorded = true;  
  246. //              log("按下,记录:%d flag:%d", downY, itemFlag);  
  247.             }  
  248.             break;  
  249.         case MotionEvent.ACTION_UP: {  
  250.             isRecorded = false;  
  251.             if (onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.willrefresh) {  
  252.                 doRefresh();  
  253.             } else if (refreshView.getRefreshStatus() == RefreshStatus.normal) {  
  254.                 refreshView.setPadding(0, -1 * refreshView.height, 00);  
  255.             }  
  256.   
  257.             if (onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.willrefresh) {  
  258.                 doMore();  
  259.             } else if (moreView.getRefreshStatus() == RefreshStatus.normal) {  
  260.                 moreView.setPadding(000, -1 * moreView.height);  
  261.             }  
  262.             break;  
  263.         }  
  264.         case MotionEvent.ACTION_MOVE: {  
  265.             if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal ||   
  266.                     itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {  
  267.                 downY = (int) ev.getY(0);  
  268.                 isRecorded = true;  
  269. //              log("按下,记录:%d flag:%d", downY, itemFlag);  
  270.             } else if (isRecorded) {  
  271.                 int nowY = (int) ev.getY(0);  
  272.                 int offset = nowY - downY;  
  273.                 if (offset > 0 && itemFlag == ITEM_FLAG_FIRST) {  
  274.                     // 下拉  
  275.                     setSelection(0);  
  276.                     if (offset >= (minTimesToRefresh * refreshView.height)) {  
  277.                         refreshView.setRefreshStatus(RefreshStatus.willrefresh);  
  278.                     } else {  
  279.                         refreshView.setRefreshStatus(RefreshStatus.normal);  
  280.                     }  
  281.   
  282.                     refreshView.setPadding(0, -1 * (refreshView.height - offset), 00);  
  283.                 } else if(itemFlag == ITEM_FLAG_LAST){  
  284.                     // 上拉  
  285.                     setSelection(this.getCount());  
  286.                     if (offset <= -1 * (minTimesToRefresh * moreView.height)) {  
  287.                         moreView.setRefreshStatus(RefreshStatus.willrefresh);  
  288.                     } else {  
  289.                         moreView.setRefreshStatus(RefreshStatus.normal);  
  290.                     }  
  291.                     moreView.setPadding(000, -1 * (moreView.height + offset));  
  292.                 }  
  293. //              log("位移:%d", offset);  
  294.             }  
  295.             break;  
  296.         }  
  297.         default:  
  298.             break;  
  299.         }  
  300.         return super.onTouchEvent(ev);  
  301.     }  
  302.   
  303.     /** 
  304.      * 开始刷新 
  305.      */  
  306.     private void doRefresh(){  
  307. //      log("开始刷新");  
  308.         refreshView.setRefreshStatus(RefreshStatus.refreshing);  
  309.         refreshView.setPadding(0000);  
  310.         if(onRefreshListener.onRefreshOrMore(thistrue))  
  311.             doneRefresh();  
  312.     }  
  313.       
  314.     /** 
  315.      * 开始加载更多 
  316.      */  
  317.     private void doMore(){  
  318. //      log("加载更多");  
  319.         moreView.setRefreshStatus(RefreshStatus.refreshing);  
  320.         moreView.setPadding(0000);  
  321.         if(onMoreListener.onRefreshOrMore(thisfalse))  
  322.             doneMore();  
  323.     }  
  324.       
  325.     /** 
  326.      * 刷新完成之后调用,用于取消刷新的动画 
  327.      */  
  328.     public void doneRefresh() {  
  329. //      log("刷新完成!");  
  330.         refreshView.setRefreshStatus(RefreshStatus.normal);  
  331.         refreshView.setPadding(0, -1 * refreshView.height, 00);  
  332.     }  
  333.       
  334.     /** 
  335.      * 加载更多完成之后调用,用于取消加载更多的动画 
  336.      */  
  337.     public void doneMore() {  
  338. //      log("加载完成!");  
  339.         moreView.setRefreshStatus(RefreshStatus.normal);  
  340.         moreView.setPadding(000, -1 * moreView.height);  
  341.     }  
  342.   
  343.     /** 
  344.      * 获取刷新的状态 
  345.      * @return  一般 将要刷新 刷新完成 
  346.      */  
  347.     public RefreshStatus getRefreshStatus(){  
  348.         return refreshView.getRefreshStatus();  
  349.     }  
  350.     /** 
  351.      * 获取加载更多的状态 
  352.      * @return  一般 将要加载 加载完成 
  353.      */  
  354.     public RefreshStatus getMoreStatus(){  
  355.         return moreView.getRefreshStatus();  
  356.     }  
  357.       
  358. //  private void log(Object obj) {  
  359. //      log("%s", obj.toString());  
  360. //  }  
  361. //  
  362. //  private void log(String format, Object... args) {  
  363. //      Log.i("DynamicListView", String.format(format, args));  
  364. //  }  
  365. }  

使用例子:
  1. package com.sin.android.ui;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5.   
  6. import android.annotation.SuppressLint;  
  7. import android.app.Activity;  
  8. import android.os.Bundle;  
  9. import android.os.Handler;  
  10. import android.os.Message;  
  11. import android.util.Log;  
  12. import android.view.View;  
  13. import android.widget.AdapterView;  
  14. import android.widget.AdapterView.OnItemClickListener;  
  15. import android.widget.ArrayAdapter;  
  16. import android.widget.Toast;  
  17.   
  18. import com.sin.android.ui.DynamicListView.DynamicListViewListener;  
  19.   
  20. @SuppressLint("HandlerLeak")  
  21. public class MainActivity extends Activity implements DynamicListViewListener {  
  22.     DynamicListView listView;  
  23.     ArrayList<String> data;  
  24.     ArrayAdapter<String> adapter;  
  25.       
  26.     // 用于刷新控件状态  
  27.     Handler handler = new Handler() {  
  28.         @Override  
  29.         public void handleMessage(Message msg) {  
  30.             if (msg.what == 0) {  
  31.                 adapter.notifyDataSetChanged();  
  32.                 listView.doneRefresh();  
  33.                 Toast.makeText(MainActivity.this"新加载"+msg.arg1+"条数据!", Toast.LENGTH_LONG).show();  
  34.             } else if (msg.what == 1) {  
  35.                 adapter.notifyDataSetChanged();  
  36.                 listView.doneMore();  
  37.             } else {  
  38.                 super.handleMessage(msg);  
  39.             }  
  40.         }  
  41.     };  
  42.   
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.         listView = new DynamicListView(this);  
  47.         setContentView(listView);  
  48.   
  49.         data = new ArrayList<String>();  
  50.         for (int i = 1; i < 10; ++i) {  
  51.             data.add("原始数据" + i);  
  52.         }  
  53.         adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, data);  
  54.         listView.setAdapter(adapter);  
  55.         listView.setOnItemClickListener(new OnItemClickListener() {  
  56.             @Override  
  57.             public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {  
  58.                 Log.i("",data.get(arg2-1));  
  59.             }  
  60.         });  
  61.         listView.setDoMoreWhenBottom(false);    // 滚动到低端的时候不自己加载更多  
  62.         listView.setOnRefreshListener(this);  
  63.         listView.setOnMoreListener(this);  
  64.     }  
  65.   
  66.     @Override  
  67.     public boolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh) {  
  68.         if (isRefresh) {  
  69.             new Thread(new Runnable() {  
  70.                 @Override  
  71.                 public void run() {  
  72.                     // 刷新  
  73.                     ArrayList<String> temp = new ArrayList<String>();  
  74.                     for (int i = 0; i < 3; ++i) {  
  75.                         temp.add(0new Date().toLocaleString());  
  76.                         try {  
  77.                             Thread.sleep(1000);  
  78.                         } catch (InterruptedException e) {  
  79.                             e.printStackTrace();  
  80.                         }  
  81.                     }  
  82.                     synchronized (data) {  
  83.                         data.addAll(0, temp);  
  84.                     }  
  85.                       
  86.                     Message message = new Message();  
  87.                     message.what = 0;  
  88.                     message.arg1 = temp.size();  
  89.                     handler.sendMessage(message);  
  90.                 }  
  91.             }).start();  
  92.         } else {  
  93.             new Thread(new Runnable() {  
  94.                 @Override  
  95.                 public void run() {  
  96.                     // 加载更多  
  97.                     ArrayList<String> temp = new ArrayList<String>();  
  98.                     for (int i = 0; i < 3; ++i) {  
  99.                         temp.add(new Date().toLocaleString());  
  100.                         try {  
  101.                             Thread.sleep(1000);  
  102.                         } catch (InterruptedException e) {  
  103.                             e.printStackTrace();  
  104.                         }  
  105.                     }  
  106.                     synchronized (data) {  
  107.                         data.addAll(temp);  
  108.                     }  
  109.                     handler.sendEmptyMessage(1);  
  110.                 }  
  111.             }).start();  
  112.         }  
  113.         return false;  
  114.     }  
  115. }  


截图:





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值