1. 程式人生 > >Android ListView列表 重新整理和載入更多

Android ListView列表 重新整理和載入更多

上下拉實現重新整理和載入更多的ListView,如下:

[java] view plaincopyprint?
  1. package com.sin.android.ui;  
  2. import android.content.Context;  
  3. import android.util.AttributeSet;  
  4. import android.view.Gravity;  
  5. import android.view.MotionEvent;  
  6. import android.view.View;  
  7. import android.widget.AbsListView;  
  8. import android.widget.AbsListView.OnScrollListener;  
  9. import android.widget.LinearLayout;  
  10. import android.widget.ListView;  
  11. import android.widget.ProgressBar;  
  12. import android.widget.TextView;  
  13. /** 
  14.  * 動態重新整理和載入資料ListView 
  15.  * @author RobinTang 
  16.  * 
  17.  */
  18. publicclass DynamicListView extends ListView implements OnScrollListener {  
  19.     /** 
  20.      * 監聽器 
  21.      * 監聽控制元件的重新整理或者載入更多事件
     
  22.      * 所有的條目事件都會有一個偏移量,也就是position應該減1才是你介面卡中的條目 
  23.      * @author RobinTang 
  24.      * 
  25.      */
  26.     publicinterface DynamicListViewListener {  
  27.         /** 
  28.          *  
  29.          * @param dynamicListView 
  30.          * @param isRefresh 為true的時候代表的是重新整理,為false的時候代表的是載入更多 
  31.          * @return true:重新整理或者載入更多動作完成,重新整理或者載入更多的動畫自動消失 false:重新整理或者載入更多為完成,需要在資料載入完成之後去呼叫控制元件的doneRefresh()或者doneMore()方法 
     
  32.          */
  33.         publicboolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh);  
  34.     }  
  35.     /** 
  36.      * 狀態控制元件(StatusView,列表頭上和底端的)的狀態列舉 
  37.      * @author RobinTang 
  38.      * 
  39.      */
  40.     enum RefreshStatus {  
  41.         none, normal, willrefresh, refreshing  
  42.     }  
  43.     /** 
  44.      * 狀態控制元件 
  45.      * @author RobinTang 
  46.      * 
  47.      */
  48.     class StatusView extends LinearLayout {  
  49.         publicint height;  
  50.         publicint width;  
  51.         private ProgressBar progressBar = null;  
  52.         private TextView textView = null;  
  53.         private RefreshStatus refreshStatus = RefreshStatus.none;  
  54.         private String normalString = "下拉重新整理";  
  55.         private String willrefreshString = "鬆開重新整理";  
  56.         private String refreshingString = "正在重新整理";  
  57.         public StatusView(Context context, AttributeSet attrs) {  
  58.             super(context, attrs);  
  59.             initThis(context);  
  60.         }  
  61.         public StatusView(Context context) {  
  62.             super(context);  
  63.             initThis(context);  
  64.         }  
  65.         privatevoid initThis(Context context) {  
  66.             this.setOrientation(LinearLayout.HORIZONTAL);  
  67.             this.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);  
  68.             progressBar = new ProgressBar(context);  
  69.             progressBar.setLayoutParams(new LinearLayout.LayoutParams(3030));  
  70.             textView = new TextView(context);  
  71.             textView.setPadding(5000);  
  72.             this.addView(progressBar);  
  73.             this.addView(textView);  
  74.             int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  75.             int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  76.             this.measure(w, h);  
  77.             height = this.getMeasuredHeight();  
  78.             width = this.getMeasuredWidth();  
  79.             this.setRefreshStatus(RefreshStatus.normal);  
  80.         }  
  81.         public RefreshStatus getRefreshStatus() {  
  82.             return refreshStatus;  
  83.         }  
  84.         publicvoid setRefreshStatus(RefreshStatus refreshStatus) {  
  85.             if (this.refreshStatus != refreshStatus) {  
  86.                 this.refreshStatus = refreshStatus;  
  87.                 if(refreshStatus == RefreshStatus.refreshing){  
  88.                     this.progressBar.setVisibility(View.VISIBLE);  
  89.                 }  
  90.                 else{  
  91.                     this.progressBar.setVisibility(View.GONE);  
  92.                 }  
  93.                 refreshStatusString();  
  94.                 this.invalidate();  
  95.             }  
  96.         }  
  97.         privatevoid refreshStatusString() {  
  98.             switch (refreshStatus) {  
  99.             case normal:  
  100.                 textView.setText(normalString);  
  101.                 progressBar.setProgress(0);  
  102.                 break;  
  103.             case willrefresh:  
  104.                 textView.setText(willrefreshString);  
  105.                 break;  
  106.             case refreshing:  
  107.                 textView.setText(refreshingString);  
  108.                 break;  
  109.             default:  
  110.                 break;  
  111.             }  
  112.         }  
  113.         /** 
  114.          * 設定狀態字串 
  115.          * @param normalString  平時的字串 
  116.          * @param willrefreshString 鬆開後重新整理(或載入)的字串 
  117.          * @param refreshingString  正在重新整理(或載入)的字串 
  118.          */
  119.         publicvoid setStatusStrings(String normalString, String willrefreshString, String refreshingString){  
  120.             this.normalString = normalString;  
  121.             this.willrefreshString = willrefreshString;  
  122.             this.refreshingString = refreshingString;  
  123.             this.refreshStatusString();  
  124.         }  
  125.     }  
  126.     private StatusView refreshView;  
  127.     private StatusView moreView;  
  128.     privateint itemFlag = -1;  
  129.     privateboolean isRecorded = false;  
  130.     privateint downY = -1;  
  131.     privatefinalfloat minTimesToRefresh = 1.5f;  
  132.     privatefinalstaticint ITEM_FLAG_FIRST = 1;  
  133.     privatefinalstaticint ITEM_FLAG_NONE = 0;  
  134.     privatefinalstaticint ITEM_FLAG_LAST = -1;  
  135.     // 兩個監聽器
  136.     private DynamicListViewListener onRefreshListener;  
  137.     private DynamicListViewListener onMoreListener;  
  138.     // 滾動到低端的時候是否自動載入更多
  139.     privateboolean doMoreWhenBottom = false;  
  140.     public DynamicListView(Context context, AttributeSet attrs, int defStyle) {  
  141.         super(context, attrs, defStyle);  
  142.         initThis(context);  
  143.     }  
  144.     public DynamicListView(Context context, AttributeSet attrs) {  
  145.         super(context, attrs);  
  146.         initThis(context);  
  147.     }  
  148.     public DynamicListView(Context context) {  
  149.         super(context);  
  150.         initThis(context);  
  151.     }  
  152.     privatevoid initThis(Context context) {  
  153.         refreshView = new StatusView(context);  
  154.         moreView = new StatusView(context);  
  155.         refreshView.setStatusStrings("繼續下拉重新整理資料...""鬆開之後重新整理資料...""正在重新整理資料...");  
  156.         moreView.setStatusStrings("繼續上拉載入資料...""鬆開之後載入資料...""正在載入資料...");  
  157.         this.addHeaderView(refreshView, nullfalse);  
  158.         this.addFooterView(moreView, nullfalse);  
  159.         this.setOnScrollListener(this);  
  160.         doneRefresh();  
  161.         doneMore();  
  162.     }  
  163.     // 監聽器操作
  164.     public DynamicListViewListener getOnRefreshListener() {  
  165.         return onRefreshListener;  
  166.     }  
  167.     publicvoid setOnRefreshListener(DynamicListViewListener onRefreshListener) {  
  168.         this.onRefreshListener = onRefreshListener;  
  169.     }  
  170.     public DynamicListViewListener getOnMoreListener() {  
  171.         return onMoreListener;  
  172.     }  
  173.     publicvoid setOnMoreListener(DynamicListViewListener onMoreListener) {  
  174.         this.onMoreListener = onMoreListener;  
  175.     }  
  176.     // 設定
  177.     publicboolean isDoMoreWhenBottom() {  
  178.         return doMoreWhenBottom;  
  179.     }  
  180.     publicvoid setDoMoreWhenBottom(boolean doMoreWhenBottom) {  
  181.         this.doMoreWhenBottom = doMoreWhenBottom;  
  182.     }  
  183.     @Override
  184.     publicvoid onScroll(AbsListView l, int t, int oldl, int count) {  
  185.         // log("%d %d %d", t, oldl, count);
  186.         if (t == 0)  
  187.             itemFlag = ITEM_FLAG_FIRST;  
  188.         elseif ((t + oldl) == count){  
  189.             itemFlag = ITEM_FLAG_LAST;  
  190.             if(doMoreWhenBottom && onMoreListener != null && moreView.getRefreshStatus() != RefreshStatus.refreshing){  
  191.                     doMore();  
  192.             }  
  193.         }  
  194.         else {  
  195.             itemFlag = ITEM_FLAG_NONE;  
  196. //          isRecorded = false;
  197.         }  
  198.     }  
  199.     @Override
  200.     publicvoid onScrollStateChanged(AbsListView arg0, int arg1) {  
  201.     }  
  202.     @Override
  203.     publicboolean onTouchEvent(MotionEvent ev) {  
  204.         switch (ev.getAction()) {  
  205.         case MotionEvent.ACTION_DOWN:  
  206.             if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal || itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {  
  207.                 downY = (int) ev.getY(0);  
  208.                 isRecorded = true;  
  209. //              log("按下,記錄:%d flag:%d", downY, itemFlag);
  210.             }  
  211.             break;  
  212.         case MotionEvent.ACTION_UP: {  
  213.             isRecorded = false;  
  214.             if (onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.willrefresh) {  
  215.                 doRefresh();  
  216.             } elseif (refreshView.getRefreshStatus() == RefreshStatus.normal) {  
  217.                 refreshView.setPadding(0, -1 * refreshView.height, 00);  
  218.             }  
  219.             if (onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.willrefresh) {  
  220.                 doMore();  
  221.             } elseif (moreView.getRefreshStatus() == RefreshStatus.normal) {  
  222.                 moreView.setPadding(000, -1 * moreView.height);  
  223.             }  
  224.             break;  
  225.         }  
  226.         case MotionEvent.ACTION_MOVE: {  
  227.             if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal ||   
  228.                     itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {  
  229.                 downY = (int) ev.getY(0);  
  230.                 isRecorded = true;  
  231. //              log("按下,記錄:%d flag:%d", downY, itemFlag);
  232.             } elseif (isRecorded) {  
  233.                 int nowY = (int) ev.getY(0);  
  234.                 int offset = nowY - downY;  
  235.                 if (offset > 0 && itemFlag == ITEM_FLAG_FIRST) {  
  236.                     // 下拉
  237.                     setSelection(0);  
  238.                     if (offset >= (minTimesToRefresh * refreshView.height)) {  
  239.                         refreshView.setRefreshStatus(RefreshStatus.willrefresh);  
  240.                     } else {  
  241.                         refreshView.setRefreshStatus(RefreshStatus.normal);  
  242.                     }  
  243.                     refreshView.setPadding(0, -1 * (refreshView.height - offset), 00);  
  244.                 } elseif(itemFlag == ITEM_FLAG_LAST){  
  245.                     // 上拉
  246.                     setSelection(this.getCount());  
  247.                     if (offset <= -1 * (minTimesToRefresh * moreView.height)) {  
  248.                         moreView.setRefreshStatus(RefreshStatus.willrefresh);  
  249.                     } else {  
  250.                         moreView.setRefreshStatus(RefreshStatus.normal);  
  251.                     }  
  252.                     moreView.setPadding(000, -1 * (moreView.height + offset));  
  253.                 }  
  254. //              log("位移:%d", offset);
  255.             }  
  256.             break;  
  257.         }  
  258.         default:  
  259.             break;  
  260.         }  
  261.         returnsuper.onTouchEvent(ev);  
  262.     }  
  263.     /** 
  264.      * 開始重新整理 
  265.      */
  266.     privatevoid doRefresh(){  
  267. //      log("開始重新整理");
  268.         refreshView.setRefreshStatus(RefreshStatus.refreshing);  
  269.         refreshView.setPadding(0000);  
  270.         if(onRefreshListener.onRefreshOrMore(thistrue))  
  271.             doneRefresh();  
  272.     }  
  273.     /** 
  274.      * 開始載入更多 
  275.      */
  276.     privatevoid doMore(){  
  277. //      log("載入更多");
  278.         moreView.setRefreshStatus(RefreshStatus.refreshing);  
  279.         moreView.setPadding(0000);  
  280.         if(onMoreListener.onRefreshOrMore(thisfalse))  
  281.             doneMore();  
  282.     }  
  283.     /** 
  284.      * 重新整理完成之後呼叫,用於取消重新整理的動畫 
  285.      */
  286.     publicvoid doneRefresh() {  
  287. //      log("重新整理完成!");
  288.         refreshView.setRefreshStatus(RefreshStatus.normal);  
  289.         refreshView.setPadding(0, -1 * refreshView.height, 00);  
  290.     }  
  291.     /** 
  292.      * 載入更多完成之後呼叫,用於取消載入更多的動畫 
  293.      */
  294.     publicvoid doneMore() {  
  295. //      log("載入完成!");
  296.         moreView.setRefreshStatus(RefreshStatus.normal);  
  297.         moreView.setPadding(000, -1 * moreView.height);  
  298.     }  
  299.     /** 
  300.      * 獲取重新整理的狀態 
  301.      * @return  一般 將要重新整理 重新整理完成 
  302.      */
  303.     public RefreshStatus getRefreshStatus(){  
  304.         return refreshView.getRefreshStatus();  
  305.     }  
  306.     /** 
  307.      * 獲取載入更多的狀態 
  308.      * @return  一般 將要載入 載入完成 
  309.      */
  310.     public RefreshStatus getMoreStatus(){  
  311.         return moreView.getRefreshStatus();  
  312.     }  
  313. //  private void log(Object obj) {
  314. //      log("%s", obj.toString());
  315. //  }
  316. //
  317. //  private void log(String format, Object... args) {
  318. //      Log.i("DynamicListView", String.format(format, args));
  319. //  }
  320. }  

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

截圖: