Android UI--自定義ListView(實現下拉刷新+加載更多)

http://blog.csdn.net/wwj_748/article/details/12512885html

Android UI--自定義ListView(實現下拉刷新+加載更多)

關於實現ListView下拉刷新和加載更多的實現,我想網上一搜就一堆。不過我就沒發現比較實用的,要不就是實現起來太複雜,要不就是不健全的。由於小巫近期要開發新浪微博客戶端,須要實現ListView的下拉刷新,因此就想把這個UI整合到項目當中去,這裏只是一個demo,能夠根據項目的須要進行修改。

就不要太在意界面了哈








知道大家想要源碼了,去下吧:http://download.csdn.net/detail/wwj_748/6373183


自定義ListView:
[java]  view plain copy
  1. package com.markupartist.android.widget;  
  2.   
  3.   
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import com.markupartist.android.example.pulltorefresh.R;  
  8.   
  9. import android.content.Context;  
  10. import android.util.AttributeSet;  
  11. import android.util.Log;  
  12. import android.view.LayoutInflater;  
  13. import android.view.MotionEvent;  
  14. import android.view.View;  
  15. import android.view.ViewGroup;  
  16. import android.view.animation.LinearInterpolator;  
  17. import android.view.animation.RotateAnimation;  
  18. import android.widget.AbsListView;  
  19. import android.widget.AbsListView.OnScrollListener;  
  20. import android.widget.ImageView;  
  21. import android.widget.ListAdapter;  
  22. import android.widget.ListView;  
  23. import android.widget.ProgressBar;  
  24. import android.widget.RelativeLayout;  
  25. import android.widget.TextView;  
  26.   
  27.   
  28.   
  29. /** 
  30.  * 2013/8/13 
  31.  * 自定義ListView,實現OnScrollListener接口 
  32.  * 此ListView是爲實現"下拉刷新"和"上拉加載更多"而定製的,具體效果可參考新浪微博、騰訊微博 
  33.  * @author wwj 
  34.  * 
  35.  */  
  36. public class PullToRefreshListView extends ListView implements OnScrollListener {  
  37.   
  38.     private static final int TAP_TO_REFRESH = 1;            //(未刷新)  
  39.     private static final int PULL_TO_REFRESH = 2;           // 下拉刷新  
  40.     private static final int RELEASE_TO_REFRESH = 3;        // 釋放刷新  
  41.     private static final int REFRESHING = 4;                // 正在刷新  
  42.     private static final int TAP_TO_LOADMORE = 5;           // 未加載更多  
  43.     private static final int LOADING = 6;                   // 正在加載  
  44.       
  45.   
  46.     private static final String TAG = "PullToRefreshListView";  
  47.   
  48.     private OnRefreshListener mOnRefreshListener;           // 刷新監聽器  
  49.   
  50.     /** 
  51.      * Listener that will receive notifications every time the list scrolls. 
  52.      */  
  53.     private OnScrollListener mOnScrollListener;             // 列表滾動監聽器  
  54.     private LayoutInflater mInflater;                       // 用於加載佈局文件  
  55.   
  56.     private RelativeLayout mRefreshHeaderView;              // 刷新視圖(也就是頭部那部分)     
  57.     private TextView mRefreshViewText;                      // 刷新提示文本         
  58.     private ImageView mRefreshViewImage;                    // 刷新向上向下的那個圖片  
  59.     private ProgressBar mRefreshViewProgress;               // 這裏是圓形進度條  
  60.     private TextView mRefreshViewLastUpdated;               // 最近更新的文本  
  61.       
  62.     private RelativeLayout mLoadMoreFooterView;             // 加載更多  
  63.     private TextView mLoadMoreText;                         // 提示文本  
  64.     private ProgressBar mLoadMoreProgress;                  // 加載更多進度條  
  65.       
  66.   
  67.     private int mCurrentScrollState;                        // 當前滾動位置             
  68.     private int mRefreshState;                              // 刷新狀態   
  69.     private int mLoadState;                                 // 加載狀態  
  70.   
  71.     private RotateAnimation mFlipAnimation;                 // 下拉動畫  
  72.     private RotateAnimation mReverseFlipAnimation;          // 恢復動畫  
  73.   
  74.     private int mRefreshViewHeight;                         // 刷新視圖高度                     
  75.     private int mRefreshOriginalTopPadding;                 // 原始上部間隙  
  76.     private int mLastMotionY;                               // 記錄點擊位置  
  77.       
  78.     public PullToRefreshListView(Context context) {  
  79.         super(context);  
  80.         init(context);  
  81.     }  
  82.   
  83.     public PullToRefreshListView(Context context, AttributeSet attrs) {  
  84.         super(context, attrs);  
  85.         init(context);  
  86.     }  
  87.   
  88.     public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {  
  89.         super(context, attrs, defStyle);  
  90.         init(context);  
  91.     }  
  92.   
  93.     private void init(Context context) {  
  94.         // Load all of the animations we need in code rather than through XML  
  95.         /** 定義旋轉動畫**/  
  96.         // 參數:1.旋轉開始的角度 2.旋轉結束的角度 3. X軸伸縮模式 4.X座標的伸縮值 5.Y軸的伸縮模式 6.Y座標的伸縮值  
  97.         mFlipAnimation = new RotateAnimation(0, -180,  
  98.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  99.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  100.         mFlipAnimation.setInterpolator(new LinearInterpolator());  
  101.         mFlipAnimation.setDuration(250);                // 設置持續時間  
  102.         mFlipAnimation.setFillAfter(true);              // 動畫執行完是否停留在執行完的狀態  
  103.         mReverseFlipAnimation = new RotateAnimation(-1800,  
  104.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  105.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  106.         mReverseFlipAnimation.setInterpolator(new LinearInterpolator());  
  107.         mReverseFlipAnimation.setDuration(250);  
  108.         mReverseFlipAnimation.setFillAfter(true);  
  109.   
  110.         // 獲取LayoutInflater實例對象  
  111.         mInflater = (LayoutInflater) context.getSystemService(  
  112.                 Context.LAYOUT_INFLATER_SERVICE);  
  113.   
  114.         // 加載下拉刷新的頭部視圖  
  115.         mRefreshHeaderView = (RelativeLayout) mInflater.inflate(  
  116.                 R.layout.pull_to_refresh_header, thisfalse);  
  117.         mRefreshViewText =  
  118.             (TextView) mRefreshHeaderView.findViewById(R.id.pull_to_refresh_text);  
  119.         mRefreshViewImage =  
  120.             (ImageView) mRefreshHeaderView.findViewById(R.id.pull_to_refresh_image);  
  121.         mRefreshViewProgress =  
  122.             (ProgressBar) mRefreshHeaderView.findViewById(R.id.pull_to_refresh_progress);  
  123.         mRefreshViewLastUpdated =  
  124.             (TextView) mRefreshHeaderView.findViewById(R.id.pull_to_refresh_updated_at);  
  125.         mLoadMoreFooterView = (RelativeLayout) mInflater.inflate(  
  126.                 R.layout.loadmore_footer, thisfalse);  
  127.         mLoadMoreText = (TextView) mLoadMoreFooterView.findViewById(R.id.loadmore_text);  
  128.         mLoadMoreProgress = (ProgressBar) mLoadMoreFooterView.findViewById(R.id.loadmore_progress);  
  129.           
  130.   
  131.         mRefreshViewImage.setMinimumHeight(50);     // 設置圖片最小高度  
  132.         mRefreshHeaderView.setOnClickListener(new OnClickRefreshListener());  
  133.         mRefreshOriginalTopPadding = mRefreshHeaderView.getPaddingTop();  
  134.         mLoadMoreFooterView.setOnClickListener(new OnClickLoadMoreListener());  
  135.   
  136.         mRefreshState = TAP_TO_REFRESH;             // 初始刷新狀態  
  137.         mLoadState = TAP_TO_LOADMORE;  
  138.   
  139.         addHeaderView(mRefreshHeaderView);          // 增長頭部視圖  
  140.         addFooterView(mLoadMoreFooterView);         // 增長尾部視圖  
  141.   
  142.         super.setOnScrollListener(this);          
  143.   
  144.         measureView(mRefreshHeaderView);                // 測量視圖  
  145.         mRefreshViewHeight = mRefreshHeaderView.getMeasuredHeight();    // 獲得視圖的高度  
  146.     }  
  147.   
  148.     @Override  
  149.     protected void onAttachedToWindow() {  
  150.         setSelection(1);        // 設置當前選中的項  
  151.     }  
  152.   
  153.     @Override  
  154.     public void setAdapter(ListAdapter adapter) {  
  155.         super.setAdapter(adapter);  
  156.   
  157.         setSelection(1);  
  158.     }  
  159.   
  160.     /** 
  161.      * Set the listener that will receive notifications every time the list 
  162.      * scrolls. 
  163.      *  
  164.      * @param l The scroll listener.  
  165.      */  
  166.     @Override  
  167.     public void setOnScrollListener(AbsListView.OnScrollListener l) {  
  168.         mOnScrollListener = l;  
  169.     }  
  170.   
  171.     /** 
  172.      * Register a callback to be invoked when this list should be refreshed. 
  173.      * 註冊監聽器 
  174.      * @param onRefreshListener The callback to run. 
  175.      */  
  176.     public void setOnRefreshListener(OnRefreshListener onRefreshListener) {  
  177.         mOnRefreshListener = onRefreshListener;  
  178.     }  
  179.   
  180.     /** 
  181.      * Set a text to represent when the list was last updated. 
  182.      * 設置一個文原本表示最近更新的列表,顯示的是最近更新列表的時間 
  183.      * @param lastUpdated Last updated at. 
  184.      */  
  185.     public void setLastUpdated(CharSequence lastUpdated) {  
  186.         if (lastUpdated != null) {  
  187.             mRefreshViewLastUpdated.setVisibility(View.VISIBLE);  
  188.             mRefreshViewLastUpdated.setText("更新於: " + lastUpdated);  
  189.         } else {  
  190.             mRefreshViewLastUpdated.setVisibility(View.GONE);  
  191.         }  
  192.     }  
  193.   
  194.     @Override  
  195.     public boolean onTouchEvent(MotionEvent event) {  
  196.         final int y = (int) event.getY();    // 獲取點擊位置的Y座標  
  197.   
  198.         switch (event.getAction()) {  
  199.             case MotionEvent.ACTION_UP:     // 手指擡起  
  200.                 if (!isVerticalScrollBarEnabled()) {  
  201.                     setVerticalScrollBarEnabled(true);  
  202.                 }  
  203.                 if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {  
  204.                     if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight  
  205.                             || mRefreshHeaderView.getTop() >= 0)  
  206.                             && mRefreshState == RELEASE_TO_REFRESH) {  
  207.                         // Initiate the refresh  
  208.                         mRefreshState = REFRESHING;     // 刷新狀態  
  209.                         prepareForRefresh();  
  210.                         onRefresh();  
  211.                     } else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight  
  212.                             || mRefreshHeaderView.getTop() < 0) {  
  213.                         // Abort refresh and scroll down below the refresh view  
  214.                         resetHeader();  
  215.                         setSelection(1);  
  216.                     }  
  217.                 }  
  218.                 break;  
  219.             case MotionEvent.ACTION_DOWN:  
  220.                 mLastMotionY = y;  
  221.                 break;  
  222.             case MotionEvent.ACTION_MOVE:  
  223.                 applyHeaderPadding(event);  
  224.                 break;  
  225.         }  
  226.         return super.onTouchEvent(event);  
  227.     }  
  228.   
  229.     private void applyHeaderPadding(MotionEvent ev) {  
  230.         final int historySize = ev.getHistorySize();  
  231.   
  232.         // Workaround for getPointerCount() which is unavailable in 1.5  
  233.         // (it's always 1 in 1.5)  
  234.         int pointerCount = 1;  
  235.         try {  
  236.             Method method = MotionEvent.class.getMethod("getPointerCount");  
  237.             pointerCount = (Integer)method.invoke(ev);  
  238.         } catch (NoSuchMethodException e) {  
  239.             pointerCount = 1;  
  240.         } catch (IllegalArgumentException e) {  
  241.             throw e;  
  242.         } catch (IllegalAccessException e) {  
  243.             System.err.println("unexpected " + e);  
  244.         } catch (InvocationTargetException e) {  
  245.             System.err.println("unexpected " + e);  
  246.         }  
  247.   
  248.         for (int h = 0; h < historySize; h++) {  
  249.             for (int p = 0; p < pointerCount; p++) {  
  250.                 if (mRefreshState == RELEASE_TO_REFRESH) {  
  251.                     if (isVerticalFadingEdgeEnabled()) {  
  252.                         setVerticalScrollBarEnabled(false);  
  253.                     }  
  254.   
  255.                     int historicalY = 0;  
  256.                     try {  
  257.                         // For Android > 2.0  
  258.                         Method method = MotionEvent.class.getMethod(  
  259.                                 "getHistoricalY", Integer.TYPE, Integer.TYPE);  
  260.                         historicalY = ((Float) method.invoke(ev, p, h)).intValue();  
  261.                     } catch (NoSuchMethodException e) {  
  262.                         // For Android < 2.0  
  263.                         historicalY = (int) (ev.getHistoricalY(h));  
  264.                     } catch (IllegalArgumentException e) {  
  265.                         throw e;  
  266.                     } catch (IllegalAccessException e) {  
  267.                         System.err.println("unexpected " + e);  
  268.                     } catch (InvocationTargetException e) {  
  269.                         System.err.println("unexpected " + e);  
  270.                     }  
  271.   
  272.                     // Calculate the padding to apply, we divide by 1.7 to  
  273.                     // simulate a more resistant effect during pull.  
  274.                     int topPadding = (int) (((historicalY - mLastMotionY)  
  275.                             - mRefreshViewHeight) / 1.7);  
  276.   
  277.                     // 設置上、下、左、右四個位置的間隙間隙  
  278.                     mRefreshHeaderView.setPadding(  
  279.                             mRefreshHeaderView.getPaddingLeft(),  
  280.                             topPadding,  
  281.                             mRefreshHeaderView.getPaddingRight(),  
  282.                             mRefreshHeaderView.getPaddingBottom());  
  283.                 }  
  284.             }  
  285.         }  
  286.     }  
  287.   
  288.     /** 
  289.      * Sets the header padding back to original size. 
  290.      * 設置頭部填充會原始大小 
  291.      */  
  292.     private void resetHeaderPadding() {  
  293.         mRefreshHeaderView.setPadding(  
  294.                 mRefreshHeaderView.getPaddingLeft(),  
  295.                 mRefreshOriginalTopPadding,  
  296.                 mRefreshHeaderView.getPaddingRight(),  
  297.                 mRefreshHeaderView.getPaddingBottom());  
  298.     }  
  299.   
  300.     /** 
  301.      * Resets the header to the original state. 
  302.      * 從新設置頭部爲原始狀態 
  303.      */  
  304.     private void resetHeader() {  
  305.         if (mRefreshState != TAP_TO_REFRESH) {  
  306.             mRefreshState = TAP_TO_REFRESH;  
  307.   
  308.             resetHeaderPadding();  
  309.   
  310.             // Set refresh view text to the pull label  
  311.             mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);  
  312.             // Replace refresh drawable with arrow drawable  
  313.             mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);  
  314.             // Clear the full rotation animation  
  315.             mRefreshViewImage.clearAnimation();  
  316.             // Hide progress bar and arrow.  
  317.             mRefreshViewImage.setVisibility(View.GONE);  
  318.             mRefreshViewProgress.setVisibility(View.GONE);  
  319.         }  
  320.     }  
  321.       
  322.     /** 
  323.      * 重設ListView尾部視圖爲初始狀態 
  324.      */  
  325.     private void resetFooter() {  
  326.         if(mLoadState != TAP_TO_LOADMORE) {  
  327.             mLoadState = TAP_TO_LOADMORE;  
  328.               
  329.             // 進度條設置爲不可見  
  330.             mLoadMoreProgress.setVisibility(View.GONE);  
  331.             // 按鈕的文本替換爲「加載更多」  
  332.             mLoadMoreText.setText(R.string.loadmore_label);  
  333.         }  
  334.           
  335.     }  
  336.       
  337.   
  338.     /** 
  339.      * 測量視圖的大小 
  340.      * @param child 
  341.      */  
  342.     private void measureView(View child) {  
  343.         ViewGroup.LayoutParams p = child.getLayoutParams();  
  344.         if (p == null) {  
  345.             p = new ViewGroup.LayoutParams(  
  346.                     ViewGroup.LayoutParams.MATCH_PARENT,  
  347.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  348.         }  
  349.   
  350.         int childWidthSpec = ViewGroup.getChildMeasureSpec(0,  
  351.                 0 + 0, p.width);  
  352.         int lpHeight = p.height;  
  353.         int childHeightSpec;  
  354.         if (lpHeight > 0) {  
  355.             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);  
  356.         } else {  
  357.             childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);  
  358.         }  
  359.         child.measure(childWidthSpec, childHeightSpec);  
  360.     }  
  361.   
  362.     @Override  
  363.     public void onScroll(AbsListView view, int firstVisibleItem,  
  364.             int visibleItemCount, int totalItemCount) {  
  365.         // When the refresh view is completely visible, change the text to say  
  366.         // "Release to refresh..." and flip the arrow drawable.  
  367.         if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL  
  368.                 && mRefreshState != REFRESHING) {  
  369.             if (firstVisibleItem == 0) {        // 若是第一個可見條目爲0  
  370.                 mRefreshViewImage.setVisibility(View.VISIBLE);  // 讓指示箭頭變得可見  
  371.                 /**若是頭部視圖相對與父容器的位置大於其自身高度+20或者頭部視圖的頂部位置>0,而且要在刷新狀態不等於"釋放以刷新"**/  
  372.                 if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight + 20  
  373.                         || mRefreshHeaderView.getTop() >= 0)  
  374.                         && mRefreshState != RELEASE_TO_REFRESH) {  
  375.                     mRefreshViewText.setText(R.string.pull_to_refresh_release_label);// 設置刷新文本爲"Release to refresh..."  
  376.                     mRefreshViewImage.clearAnimation();                 // 清除動畫   
  377.                     mRefreshViewImage.startAnimation(mFlipAnimation);   // 啓動動畫  
  378.                     mRefreshState = RELEASE_TO_REFRESH;                 // 更改刷新狀態爲「釋放以刷新"  
  379.                 } else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight + 20  
  380.                         && mRefreshState != PULL_TO_REFRESH) {  
  381.                     mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);// 設置刷新文本爲"Pull to refresh..."  
  382.                     if (mRefreshState != TAP_TO_REFRESH) {  
  383.                         mRefreshViewImage.clearAnimation();  
  384.                         mRefreshViewImage.startAnimation(mReverseFlipAnimation);  
  385.                     }  
  386.                     mRefreshState = PULL_TO_REFRESH;  
  387.                 }  
  388.             } else {  
  389.                 mRefreshViewImage.setVisibility(View.GONE);         // 讓刷新箭頭不可見  
  390.                 resetHeader();  // 從新設置頭部爲原始狀態  
  391.             }  
  392.         } else if (mCurrentScrollState == SCROLL_STATE_FLING  
  393.                 && firstVisibleItem == 0  
  394.                 && mRefreshState != REFRESHING) {  
  395.             setSelection(1);  
  396.         }  
  397.   
  398.         if (mOnScrollListener != null) {  
  399.             mOnScrollListener.onScroll(view, firstVisibleItem,  
  400.                     visibleItemCount, totalItemCount);  
  401.         }  
  402.     }  
  403.   
  404.     @Override  
  405.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  406.         mCurrentScrollState = scrollState;  
  407.   
  408.         if (mOnScrollListener != null) {  
  409.             mOnScrollListener.onScrollStateChanged(view, scrollState);  
  410.         }  
  411.     }  
  412.       
  413.   
  414.     /**爲刷新作準備**/  
  415.     public void prepareForRefresh() {  
  416.         resetHeaderPadding();         
  417.   
  418.         mRefreshViewImage.setVisibility(View.GONE);         // 去掉刷新的箭頭  
  419.         // We need this hack, otherwise it will keep the previous drawable.  
  420.         mRefreshViewImage.setImageDrawable(null);  
  421.         mRefreshViewProgress.setVisibility(View.VISIBLE);   // 圓形進度條變爲可見  
  422.   
  423.         // Set refresh view text to the refreshing label  
  424.         mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);  
  425.   
  426.         mRefreshState = REFRESHING;  
  427.     }  
  428.       
  429.     /**爲加載更多作準備**/  
  430.     public void prepareForLoadMore() {  
  431.         mLoadMoreProgress.setVisibility(View.VISIBLE);     
  432.         mLoadMoreText.setText(R.string.loading_label);  
  433.         mLoadState = LOADING;  
  434.     }  
  435.   
  436.     public void onRefresh() {  
  437.         Log.d(TAG, "onRefresh");  
  438.   
  439.         if (mOnRefreshListener != null) {  
  440.             mOnRefreshListener.onRefresh();  
  441.         }  
  442.     }  
  443.       
  444.     public void OnLoadMore() {  
  445.         Log.d(TAG, "onLoadMore");  
  446.         if(mOnRefreshListener != null) {  
  447.             mOnRefreshListener.onLoadMore();  
  448.         }  
  449.     }  
  450.   
  451.     /** 
  452.      * Resets the list to a normal state after a refresh. 
  453.      * @param lastUpdated Last updated at. 
  454.      */  
  455.     public void onRefreshComplete(CharSequence lastUpdated) {  
  456.         setLastUpdated(lastUpdated);    // 顯示更新時間  
  457.         onRefreshComplete();  
  458.     }  
  459.   
  460.     /** 
  461.      * Resets the list to a normal state after a refresh. 
  462.      */  
  463.     public void onRefreshComplete() {          
  464.         Log.d(TAG, "onRefreshComplete");  
  465.   
  466.         resetHeader();  
  467.   
  468.         // If refresh view is visible when loading completes, scroll down to  
  469.         // the next item.  
  470.         if (mRefreshHeaderView.getBottom() > 0) {  
  471.             invalidateViews();  
  472.             setSelection(1);  
  473.         }  
  474.     }  
  475.       
  476.     public void onLoadMoreComplete() {  
  477.         Log.d(TAG, "onLoadMoreComplete");  
  478.         resetFooter();  
  479.     }  
  480.   
  481.     /** 
  482.      * Invoked when the refresh view is clicked on. This is mainly used when 
  483.      * there's only a few items in the list and it's not possible to drag the 
  484.      * list. 
  485.      * 點擊刷新 
  486.      */  
  487.     private class OnClickRefreshListener implements OnClickListener {  
  488.   
  489.         @Override  
  490.         public void onClick(View v) {  
  491.             if (mRefreshState != REFRESHING) {  
  492.                 prepareForRefresh();  
  493.                 onRefresh();  
  494.             }  
  495.         }  
  496.   
  497.     }  
  498.       
  499.     /** 
  500.      *  
  501.      * @author wwj 
  502.      * 加載更多 
  503.      */  
  504.     private class OnClickLoadMoreListener implements OnClickListener {  
  505.   
  506.         @Override  
  507.         public void onClick(View v) {  
  508.             if(mLoadState != LOADING) {  
  509.                 prepareForLoadMore();  
  510.                 OnLoadMore();  
  511.             }  
  512.         }  
  513.     }  
  514.   
  515.     /** 
  516.      * Interface definition for a callback to be invoked when list should be 
  517.      * refreshed. 
  518.      * 接口定義一個回調方法當列表應當被刷新 
  519.      */  
  520.     public interface OnRefreshListener {  
  521.         /** 
  522.          * Called when the list should be refreshed. 
  523.          * 當列表應當被刷新是調用這個方法 
  524.          * <p> 
  525.          * A call to {@link PullToRefreshListView #onRefreshComplete()} is 
  526.          * expected to indicate that the refresh has completed. 
  527.          */  
  528.         public void onRefresh();  
  529.           
  530.         public void onLoadMore();  
  531.     }  
  532. }  

使用方法:
[java]  view plain copy
  1. package com.markupartist.android.example.pulltorefresh;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Arrays;  
  5. import java.util.Date;  
  6. import java.util.LinkedList;  
  7.   
  8. import android.app.Activity;  
  9. import android.content.Context;  
  10. import android.os.AsyncTask;  
  11. import android.os.Bundle;  
  12. import android.widget.ArrayAdapter;  
  13.   
  14. import com.markupartist.android.widget.PullToRefreshListView;  
  15. import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;  
  16.   
  17. public class PullToRefreshActivity extends Activity {  
  18.     private LinkedList<String> mListItems;  
  19.     public static PullToRefreshListView weiboListView;  
  20.   
  21.     /** Called when the activity is first created. */  
  22.     @Override  
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.pull_to_refresh);  
  26.         weiboListView = (PullToRefreshListView) findViewById(R.id.weibolist);  
  27.   
  28.         // Set a listener to be invoked when the list should be refreshed.  
  29.         weiboListView.setOnRefreshListener(new OnRefreshListener() {  
  30.             @Override  
  31.             public void onRefresh() {  
  32.                 // Do work to refresh the list here.  
  33.                 new GetDataTask(PullToRefreshActivity.this0).execute();  
  34.             }  
  35.   
  36.             @Override  
  37.             public void onLoadMore() {  
  38.                 new GetDataTask(PullToRefreshActivity.this1).execute();  
  39.             }  
  40.         });  
  41.   
  42.         mListItems = new LinkedList<String>();  
  43.         mListItems.addAll(Arrays.asList(mStrings));  
  44.   
  45.         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,  
  46.                 android.R.layout.simple_list_item_1, mListItems);  
  47.   
  48.         weiboListView.setAdapter(adapter);  
  49.     }  
  50.   
  51.     private class GetDataTask extends AsyncTask<Void, Void, String[]> {  
  52.         private Context context;  
  53.         private int index;  
  54.   
  55.         public GetDataTask(Context context, int index) {  
  56.             this.context = context;  
  57.             this.index = index;  
  58.         }  
  59.   
  60.         @Override  
  61.         protected String[] doInBackground(Void... params) {  
  62.             // Simulates a background job.  
  63.             try {  
  64.                 Thread.sleep(2000);  
  65.             } catch (InterruptedException e) {  
  66.                 ;  
  67.             }  
  68.             return mStrings;  
  69.         }  
  70.   
  71.         @Override  
  72.         protected void onPostExecute(String[] result) {  
  73.             if (index == 0) {  
  74.                 // 將字符串「Added after refresh」添加到頂部  
  75.                 mListItems.addFirst("Added after refresh...");  
  76.   
  77.                 SimpleDateFormat format = new SimpleDateFormat(  
  78.                         "yyyy年MM月dd日  HH:mm");  
  79.                 String date = format.format(new Date());  
  80.                 // Call onRefreshComplete when the list has been refreshed.  
  81.                 weiboListView.onRefreshComplete(date);  
  82.             } else if (index == 1) {  
  83.                 mListItems.addLast("Added after loadmore...");  
  84.                 weiboListView.onLoadMoreComplete();  
  85.             }  
  86.   
  87.             super.onPostExecute(result);  
  88.         }  
  89.     }  
  90.   
  91.     public static String[] mStrings = { "一條微博""兩條微博""三條微博""四條微博""五條微博",  
  92.             "六條微博""七條微博""八條微博""九條微博""十條微博""十一條微博""十二條微博" };  
  93.   
  94. }  

下拉刷新的那個頭部佈局
/2013.08.22_PullToRefresh_ListView_Demo/res/layout/pull_to_refresh_header.xml
[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--  
  3.      Copyright (C) 2011 Johan Nilsson <http://markupartist.com>  
  4.   
  5.      Licensed under the Apache License, Version 2.0 (the "License");  
  6.      you may not use this file except in compliance with the License.  
  7.      You may obtain a copy of the License at  
  8.   
  9.           http://www.apache.org/licenses/LICENSE-2.0  
  10.   
  11.      Unless required by applicable law or agreed to in writing, software  
  12.      distributed under the License is distributed on an "AS IS" BASIS,  
  13.      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  14.      See the License for the specific language governing permissions and  
  15.      limitations under the License.  
  16. -->  
  17.   
  18. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  19.     android:layout_width="fill_parent"  
  20.     android:layout_height="fill_parent"  
  21.     android:gravity="center"  
  22.     android:paddingBottom="15dip"  
  23.     android:paddingTop="10dip" >  
  24.   
  25.     <!-- 小型圓形進度條,初始爲不可見 -->  
  26.   
  27.     <ProgressBar  
  28.         android:id="@+id/pull_to_refresh_progress"  
  29.         style="?android:attr/progressBarStyleSmall"  
  30.         android:layout_width="wrap_content"  
  31.         android:layout_height="wrap_content"  
  32.         android:layout_centerVertical="true"  
  33.         android:layout_marginLeft="30dip"  
  34.         android:layout_marginRight="20dip"  
  35.         android:layout_marginTop="10dip"  
  36.         android:indeterminate="true"  
  37.         android:visibility="gone" />  
  38.     <!-- 下拉刷新的那個箭頭 -->  
  39.   
  40.     <ImageView  
  41.         android:id="@+id/pull_to_refresh_image"  
  42.         android:layout_width="wrap_content"  
  43.         android:layout_height="wrap_content"  
  44.         android:layout_gravity="center"  
  45.         android:layout_marginLeft="30dip"  
  46.         android:layout_marginRight="20dip"  
  47.         android:gravity="center"  
  48.         android:src="@drawable/ic_pulltorefresh_arrow"  
  49.         android:visibility="gone" />  
  50.     <!-- 下拉刷新的提示文本 -->  
  51.   
  52.     <TextView  
  53.         android:id="@+id/pull_to_refresh_text"  
  54.         android:layout_width="fill_parent"  
  55.         android:layout_height="wrap_content"  
  56.         android:layout_gravity="center"  
  57.         android:gravity="center"  
  58.         android:paddingTop="5dip"  
  59.         android:text="@string/pull_to_refresh_tap_label"  
  60.         android:textAppearance="?android:attr/textAppearanceMedium"  
  61.         android:textStyle="bold" />  
  62.   
  63.     <TextView  
  64.         android:id="@+id/pull_to_refresh_updated_at"  
  65.         android:layout_width="fill_parent"  
  66.         android:layout_height="wrap_content"  
  67.         android:layout_below="@+id/pull_to_refresh_text"  
  68.         android:layout_gravity="center"  
  69.         android:gravity="center"  
  70.         android:textAppearance="?android:attr/textAppearanceSmall"  
  71.         android:visibility="gone" />  
  72.   
  73. </RelativeLayout>  

加載更多的底部佈局
/2013.08.22_PullToRefresh_ListView_Demo/res/layout/loadmore_footer.xml
[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/loadmore_layout"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="wrap_content"  
  6.     android:gravity="center"  
  7.     android:paddingBottom="15dip"  
  8.     android:paddingTop="10dip" >  
  9.   
  10. <!--     <Button  
  11.         android:id="@+id/loadmore_btn"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="60.0dip"  
  14.         android:layout_centerHorizontal="true"  
  15.         android:layout_marginTop="0.0dip"  
  16.         android:background="@drawable/weibo_list_item_selector"  
  17.         android:text="@string/loadmore_label"  
  18.         android:textColor="@color/loadmore_btn_selector"  
  19.         android:textSize="18.0sp" />  
  20.  -->  
  21.     <ProgressBar  
  22.         android:id="@+id/loadmore_progress"  
  23.         style="?android:attr/progressBarStyleSmall"  
  24.         android:layout_width="wrap_content"  
  25.         android:layout_height="wrap_content"  
  26.         android:layout_centerVertical="true"  
  27.         android:layout_marginLeft="30dip"  
  28.         android:layout_marginRight="20dip"  
  29.         android:layout_marginTop="10dip"  
  30.         android:indeterminate="true"  
  31.         android:visibility="gone" />  
  32.   
  33.    <TextView  
  34.         android:id="@+id/loadmore_text"  
  35.         android:layout_width="fill_parent"  
  36.         android:layout_height="wrap_content"  
  37.         android:layout_gravity="center"  
  38.         android:gravity="center"  
  39.         android:paddingTop="5dip"  
  40.         android:text="@string/loadmore_label"  
  41.         android:textAppearance="?android:attr/textAppearanceMedium"  
  42.         android:textStyle="bold" />  
  43.   
  44. </RelativeLayout>  

/2013.08.22_PullToRefresh_ListView_Demo/res/layout/pull_to_refresh.xml
[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <!--  
  8.     The PullToRefreshListView replaces a standard ListView widget.  
  9.         自定義列表在這  
  10.     -->  
  11.   
  12.     <com.markupartist.android.widget.PullToRefreshListView  
  13.         android:id="@+id/weibolist"  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"   
  16.         android:cacheColorHint="#00000000"  
  17.         android:fastScrollEnabled="true"/>  
  18.   
  19. </LinearLayout>
相關文章
相關標籤/搜索