XlistView上拉刷新下拉加载

 

xlistview_header.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.     <RelativeLayout  
  3.         xmlns:android="http://schemas.android.com/apk/res/android"  
  4.         android:id="@+id/xlistview_header_content"  
  5.         android:layout_width="fill_parent"  
  6.         android:layout_height="60dp" >  
  7.   
  8.         <LinearLayout  
  9.             android:layout_width="wrap_content"  
  10.             android:layout_height="wrap_content"  
  11.             android:layout_centerInParent="true"  
  12.             android:gravity="center"  
  13.             android:orientation="vertical" android:id="@+id/xlistview_header_text">  
  14.   
  15.             <TextView  
  16.                 android:id="@+id/xlistview_header_hint_textview"  
  17.                 android:layout_width="wrap_content"  
  18.                 android:layout_height="wrap_content"  
  19.                 android:text="@string/xlistview_header_hint_normal" />  
  20.   
  21.             <LinearLayout  
  22.                 android:layout_width="wrap_content"  
  23.                 android:layout_height="wrap_content"  
  24.                 android:layout_marginTop="3dp" >  
  25.   
  26.                 <TextView  
  27.                     android:layout_width="wrap_content"  
  28.                     android:layout_height="wrap_content"  
  29.                     android:text="@string/xlistview_header_last_time"  
  30.                     android:textSize="12sp" />  
  31.   
  32.                 <TextView  
  33.                     android:id="@+id/xlistview_header_time"  
  34.                     android:layout_width="wrap_content"  
  35.                     android:layout_height="wrap_content"  
  36.                     android:textSize="12sp" />  
  37.             </LinearLayout>  
  38.         </LinearLayout>  
  39.   
  40.         <ImageView  
  41.             android:id="@+id/xlistview_header_arrow"  
  42.             android:layout_width="wrap_content"  
  43.             android:layout_height="wrap_content"  
  44.             android:layout_alignLeft="@id/xlistview_header_text"  
  45.             android:layout_centerVertical="true"  
  46.             android:layout_marginLeft="-35dp"  
  47.             android:src="@drawable/xlistview_arrow"  
  48.             android:contentDescription="@null" />  
  49.   
  50.         <ProgressBar  
  51.             android:id="@+id/xlistview_header_progressbar"  
  52.             android:layout_width="30dp"  
  53.             android:layout_height="30dp"  
  54.             android:layout_alignLeft="@id/xlistview_header_text"  
  55.             android:layout_centerVertical="true"  
  56.             android:layout_marginLeft="-40dp"  
  57.             android:visibility="invisible" />  
  58.     </RelativeLayout>  

XListViewHeader.java

[html]  view plain copy
  1. /**  
  2.  * @file XListViewHeader.java  
  3.  * @description XListView's header  
  4.  */  
  5. package com.example.listviewrefresh;  
  6.   
  7. import android.content.Context;  
  8. import android.util.AttributeSet;  
  9. import android.view.Gravity;  
  10. import android.view.LayoutInflater;  
  11. import android.view.View;  
  12. import android.view.animation.Animation;  
  13. import android.view.animation.RotateAnimation;  
  14. import android.widget.ImageView;  
  15. import android.widget.LinearLayout;  
  16. import android.widget.ProgressBar;  
  17. import android.widget.RelativeLayout;  
  18. import android.widget.TextView;  
  19.   
  20. public class XListViewHeader extends LinearLayout {  
  21.     private RelativeLayout mContainer = null;     
  22.     private ImageView mArrowImageView = null;  
  23.     private ProgressBar mProgressBar = null;  
  24.     private TextView mHintTextView = null;  
  25.     private int mState = STATE_NORMAL;  
  26.   
  27.     private Animation mRotateUpAnim = null;  
  28.     private Animation mRotateDownAnim = null;  
  29.       
  30.     private final int ROTATE_ANIM_DURATION = 180;  
  31.       
  32.     public final static int STATE_NORMAL = 0;  
  33.     public final static int STATE_READY = 1;  
  34.     public final static int STATE_REFRESHING = 2;  
  35.   
  36.     public XListViewHeader(Context context) {  
  37.         super(context);  
  38.         initView(context);  
  39.     }  
  40.   
  41.     /**  
  42.      * @param context  
  43.      * @param attrs  
  44.      */  
  45.     public XListViewHeader(Context context, AttributeSet attrs) {  
  46.         super(context, attrs);  
  47.         initView(context);  
  48.     }  
  49.   
  50.     /**  
  51.      * 得到控件,初始化动画变量  
  52.      * @param context  
  53.      */  
  54.     private void initView(Context context) {  
  55.         // 初始情况,设置下拉刷新view高度为0  
  56.         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(  
  57.                 LayoutParams.MATCH_PARENT, 0);  
  58.         mContainer = (RelativeLayout) LayoutInflater.from(context).inflate(  
  59.                 R.layout.xlistview_header, null);  
  60.         addView(mContainer, lp);  
  61.         setGravity(Gravity.BOTTOM);  
  62.   
  63.         mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow);  
  64.         mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview);  
  65.         mProgressBar = (ProgressBar)findViewById(R.id.xlistview_header_progressbar);  
  66.         /*** 以0.0的位置为起始点,逆时针旋转180度,围绕自身的中心点 */  
  67.         mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,  
  68.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,  
  69.                 0.5f);  
  70.         mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);  
  71.         mRotateUpAnim.setFillAfter(true);  
  72.         /*** 以逆时针180度的位置为起始点,顺时针旋转到0.0的位置,围绕自身的中心点 */  
  73.         mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,  
  74.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,  
  75.                 0.5f);  
  76.         mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);  
  77.         mRotateDownAnim.setFillAfter(true);  
  78.     }  
  79.   
  80.     /**  
  81.      * 根据不同的状态得到不同的处理  
  82.      * @param state  
  83.      */  
  84.     public void setState(int state) {  
  85.         if (state == mState) return ;  
  86.           
  87.         if (state == STATE_REFRESHING) {      
  88.             mArrowImageView.clearAnimation();  
  89.             mArrowImageView.setVisibility(View.INVISIBLE);  
  90.             mProgressBar.setVisibility(View.VISIBLE);  
  91.         } else {      
  92.             mArrowImageView.setVisibility(View.VISIBLE);  
  93.             mProgressBar.setVisibility(View.INVISIBLE);  
  94.         }  
  95.           
  96.         switch(state){  
  97.         case STATE_NORMAL:  
  98.             if (mState == STATE_READY) {  
  99.                 mArrowImageView.startAnimation(mRotateDownAnim);  
  100.             }  
  101.             if (mState == STATE_REFRESHING) {  
  102.                 mArrowImageView.clearAnimation();  
  103.             }  
  104.             mHintTextView.setText(R.string.xlistview_header_hint_normal);  
  105.             break;  
  106.         case STATE_READY:  
  107.             if (mState != STATE_READY) {  
  108.                 mArrowImageView.clearAnimation();  
  109.                 //开始动画,逆时针旋转180度  
  110.                 mArrowImageView.startAnimation(mRotateUpAnim);  
  111.                 mHintTextView.setText(R.string.xlistview_header_hint_ready);  
  112.             }  
  113.             break;  
  114.         case STATE_REFRESHING:  
  115.             mHintTextView.setText(R.string.xlistview_header_hint_loading);  
  116.             break;  
  117.             default:  
  118.         }  
  119.           
  120.         mState = state;  
  121.     }  
  122.     /**  
  123.      * 将header.xml的高度设为参数的高度  
  124.      * @param height  
  125.      */  
  126.     public void setVisiableHeight(int height) {  
  127.         if (height < 0)  
  128.             height = 0;  
  129.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer  
  130.                 .getLayoutParams();  
  131.         lp.height = height;  
  132.         mContainer.setLayoutParams(lp);  
  133.     }  
  134.     /**  
  135.      * 得到header.xml的高度  
  136.      * @return  
  137.      */  
  138.     public int getVisiableHeight() {  
  139.         return mContainer.getHeight();  
  140.     }  
  141.   
  142. }  

xlistview_footer.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.     <RelativeLayout  
  3.         xmlns:android="http://schemas.android.com/apk/res/android"  
  4.         android:id="@+id/xlistview_footer_content"  
  5.         android:layout_width="fill_parent"  
  6.         android:layout_height="wrap_content"  
  7.         android:padding="10dp" >  
  8.   
  9.         <ProgressBar  
  10.             android:id="@+id/xlistview_footer_progressbar"  
  11.             android:layout_width="wrap_content"  
  12.             android:layout_height="wrap_content"  
  13.             android:layout_centerInParent="true"  
  14.             android:visibility="invisible" />  
  15.   
  16.         <TextView  
  17.             android:id="@+id/xlistview_footer_hint_textview"  
  18.             android:layout_width="wrap_content"  
  19.             android:layout_height="wrap_content"  
  20.             android:layout_centerInParent="true"  
  21.             android:text="@string/xlistview_footer_hint_normal" />  
  22.     </RelativeLayout>  

XListViewFooter.java

[java]  view plain copy
  1. /** 
  2.  * @file XFooterView.java 
  3.  * @description XListView's footer 
  4.  */  
  5. package com.example.listviewrefresh;  
  6.   
  7. import android.content.Context;  
  8. import android.util.AttributeSet;  
  9. import android.view.LayoutInflater;  
  10. import android.view.View;  
  11. import android.widget.LinearLayout;  
  12. import android.widget.RelativeLayout;  
  13. import android.widget.TextView;  
  14.   
  15. public class XListViewFooter extends LinearLayout {  
  16.     public final static int STATE_NORMAL = 0;  
  17.     public final static int STATE_READY = 1;  
  18.     public final static int STATE_LOADING = 2;  
  19.   
  20.     private Context mContext;  
  21.   
  22.     private View mContentView;  
  23.     private View mProgressBar;  
  24.     private TextView mHintView;  
  25.       
  26.     public XListViewFooter(Context context) {  
  27.         super(context);  
  28.         initView(context);  
  29.     }  
  30.       
  31.     public XListViewFooter(Context context, AttributeSet attrs) {  
  32.         super(context, attrs);  
  33.         initView(context);  
  34.     }  
  35.   
  36.       
  37.     public void setState(int state) {  
  38.         mHintView.setVisibility(View.INVISIBLE);  
  39.         mProgressBar.setVisibility(View.INVISIBLE);  
  40.         mHintView.setVisibility(View.INVISIBLE);  
  41.         if (state == STATE_READY) {  
  42.             mHintView.setVisibility(View.VISIBLE);  
  43.             mHintView.setText(R.string.xlistview_footer_hint_ready);  
  44.         } else if (state == STATE_LOADING) {  
  45.             mProgressBar.setVisibility(View.VISIBLE);  
  46.         } else {  
  47.             mHintView.setVisibility(View.VISIBLE);  
  48.             mHintView.setText(R.string.xlistview_footer_hint_normal);  
  49.         }  
  50.     }  
  51.       
  52.     public void setBottomMargin(int height) {  
  53.         if (height < 0return ;  
  54.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();  
  55.         lp.bottomMargin = height;  
  56.         mContentView.setLayoutParams(lp);  
  57.     }  
  58.       
  59.     public int getBottomMargin() {  
  60.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();  
  61.         return lp.bottomMargin;  
  62.     }  
  63.       
  64.       
  65.     /** 
  66.      * normal status 
  67.      */  
  68.     public void normal() {  
  69.         mHintView.setVisibility(View.VISIBLE);  
  70.         mProgressBar.setVisibility(View.GONE);  
  71.     }  
  72.       
  73.       
  74.     /** 
  75.      * loading status  
  76.      */  
  77.     public void loading() {  
  78.         mHintView.setVisibility(View.GONE);  
  79.         mProgressBar.setVisibility(View.VISIBLE);  
  80.     }  
  81.       
  82.     /** 
  83.      * hide footer when disable pull load more 
  84.      */  
  85.     public void hide() {  
  86.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();  
  87.         lp.height = 0;  
  88.         mContentView.setLayoutParams(lp);  
  89.     }  
  90.       
  91.     /** 
  92.      * show footer 
  93.      */  
  94.     public void show() {  
  95.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();  
  96.         lp.height = LayoutParams.WRAP_CONTENT;  
  97.         mContentView.setLayoutParams(lp);  
  98.     }  
  99.       
  100.     private void initView(Context context) {  
  101.         mContext = context;  
  102.         RelativeLayout moreView = (RelativeLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);  
  103.         addView(moreView);  
  104.         moreView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));  
  105.           
  106.         mContentView = moreView.findViewById(R.id.xlistview_footer_content);  
  107.         mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar);  
  108.         mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);  
  109.     }  
  110.       
  111.       
  112. }  

 XListView.java

[java]  view plain copy
  1. /** 
  2.  * @file XListView.java 
  3.  * @description An ListView support (a) Pull down to refresh, (b) Pull up to load more. 
  4.  *      Implement IXListViewListener, and see stopRefresh() / stopLoadMore(). 
  5.  */  
  6. package com.example.listviewrefresh;  
  7.   
  8. import android.content.Context;  
  9. import android.util.AttributeSet;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12. import android.view.ViewTreeObserver.OnGlobalLayoutListener;  
  13. import android.view.animation.DecelerateInterpolator;  
  14. import android.widget.AbsListView;  
  15. import android.widget.AbsListView.OnScrollListener;  
  16. import android.widget.ListAdapter;  
  17. import android.widget.ListView;  
  18. import android.widget.RelativeLayout;  
  19. import android.widget.Scroller;  
  20. import android.widget.TextView;  
  21.   
  22. public class XListView extends ListView implements OnScrollListener {  
  23.   
  24.     private float mLastY = -1// save event y  
  25.     private Scroller mScroller; // used for scroll back  
  26.     private OnScrollListener mScrollListener; // user's scroll listener  
  27.   
  28.     // the interface to trigger refresh and load more.  
  29.     private IXListViewListener mListViewListener;  
  30.   
  31.     // -- header view  
  32.     private XListViewHeader mHeaderView;  
  33.     // header view content, use it to calculate the Header's height. And hide it  
  34.     // when disable pull refresh.  
  35.     private RelativeLayout mHeaderViewContent;  
  36.     private TextView mHeaderTimeView;  
  37.     private int mHeaderViewHeight; // header view's height  
  38.     private boolean mEnablePullRefresh = true;  
  39.     private boolean mPullRefreshing = false// is refreashing.  
  40.   
  41.     // -- footer view  
  42.     private XListViewFooter mFooterView;  
  43.     private boolean mEnablePullLoad;  
  44.     private boolean mPullLoading;  
  45.     private boolean mIsFooterReady = false;  
  46.       
  47.     // total list items, used to detect is at the bottom of listview.  
  48.     private int mTotalItemCount;  
  49.   
  50.     // for mScroller, scroll back from header or footer.  
  51.     private int mScrollBack;  
  52.     private final static int SCROLLBACK_HEADER = 0;  
  53.     private final static int SCROLLBACK_FOOTER = 1;  
  54.   
  55.     private final static int SCROLL_DURATION = 400// scroll back duration  
  56. //  private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px  at bottom, trigger load more.  
  57.     private final static int PULL_LOAD_MORE_DELTA = 25;  
  58.     private final static float OFFSET_RADIO = 1.8f; // support iOS like pull feature.  
  59.   
  60.     /** 
  61.      * @param context 
  62.      */  
  63.     public XListView(Context context) {  
  64.         super(context);  
  65.         initWithContext(context);  
  66.     }  
  67.   
  68.     public XListView(Context context, AttributeSet attrs) {  
  69.         super(context, attrs);  
  70.         initWithContext(context);  
  71.     }  
  72.   
  73.     public XListView(Context context, AttributeSet attrs, int defStyle) {  
  74.         super(context, attrs, defStyle);  
  75.         initWithContext(context);  
  76.     }  
  77.   
  78.     private void initWithContext(Context context) {   
  79.         mScroller = new Scroller(context, new DecelerateInterpolator());  
  80.         // XListView need the scroll event, and it will dispatch the event to  
  81.         // user's listener (as a proxy).  
  82.         super.setOnScrollListener(this);  
  83.   
  84.         // init header view  
  85.         mHeaderView = new XListViewHeader(context);  
  86.         mHeaderViewContent = (RelativeLayout) mHeaderView  
  87.                 .findViewById(R.id.xlistview_header_content);  
  88.         mHeaderTimeView = (TextView) mHeaderView  
  89.                 .findViewById(R.id.xlistview_header_time);  
  90.         addHeaderView(mHeaderView);  
  91.   
  92.         // init footer view  
  93.         mFooterView = new XListViewFooter(context);  
  94.   
  95.         // init header height  
  96.         mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(  
  97.                 new OnGlobalLayoutListener() {  
  98.                     @Override  
  99.                     public void onGlobalLayout() {  
  100.                         mHeaderViewHeight = mHeaderViewContent.getHeight();  
  101.                         getViewTreeObserver()  
  102.                                 .removeGlobalOnLayoutListener(this);  
  103.                     }  
  104.                 });  
  105.     }  
  106.   
  107.     @Override  
  108.     public void setAdapter(ListAdapter adapter) {  
  109.         // make sure XListViewFooter is the last footer view, and only add once.  
  110.         if (mIsFooterReady == false) {  
  111.             mIsFooterReady = true;  
  112.             addFooterView(mFooterView);  
  113.         }  
  114.         super.setAdapter(adapter);  
  115.     }  
  116.   
  117.     /** 
  118.      * enable or disable pull down refresh feature.   
  119.      * @param enable 
  120.      */  
  121.     public void setPullRefreshEnable(boolean enable) {  
  122.         mEnablePullRefresh = enable;  
  123.         if (!mEnablePullRefresh) { // disable, hide the content  
  124.             mHeaderViewContent.setVisibility(View.INVISIBLE);  
  125.         } else {  
  126.             mHeaderViewContent.setVisibility(View.VISIBLE);  
  127.         }  
  128.     }  
  129.   
  130.     /** 
  131.      * enable or disable pull up load more feature. 
  132.      * @param enable 
  133.      */  
  134.     public void setPullLoadEnable(boolean enable) {  
  135.         mEnablePullLoad = enable;  
  136.         if (!mEnablePullLoad) {  
  137.             mFooterView.hide();  
  138.             mFooterView.setOnClickListener(null);  
  139.         } else {  
  140.             mPullLoading = false;  
  141.             mFooterView.show();  
  142.             mFooterView.setState(XListViewFooter.STATE_NORMAL);  
  143.             // both "pull up" and "click" will invoke load more.  
  144.             mFooterView.setOnClickListener(new OnClickListener() {  
  145.                 @Override  
  146.                 public void onClick(View v) {  
  147.                     startLoadMore();  
  148.                 }  
  149.             });  
  150.         }  
  151.     }  
  152.   
  153.     /** 
  154.      * stop refresh, reset header view. 
  155.      */  
  156.     public void stopRefresh() {  
  157.         if (mPullRefreshing == true) {  
  158.             mPullRefreshing = false;  
  159.             resetHeaderHeight();  
  160.         }  
  161.     }  
  162.   
  163.     /** 
  164.      * stop load more, reset footer view. 
  165.      */  
  166.     public void stopLoadMore() {  
  167.         if (mPullLoading == true) {  
  168.             mPullLoading = false;  
  169.             mFooterView.setState(XListViewFooter.STATE_NORMAL);  
  170.         }  
  171.     }  
  172.   
  173.     /** 
  174.      * set last refresh time  
  175.      * @param time 
  176.      */  
  177.     public void setRefreshTime(String time) {  
  178.         mHeaderTimeView.setText(time);  
  179.     }  
  180.   
  181.     private void invokeOnScrolling() {  
  182.         if (mScrollListener instanceof OnXScrollListener) {  
  183.             OnXScrollListener l = (OnXScrollListener) mScrollListener;  
  184.             l.onXScrolling(this);  
  185.         }  
  186.     }  
  187.   
  188.     private void updateHeaderHeight(float delta) {  
  189.         mHeaderView.setVisiableHeight((int) delta  
  190.                 + mHeaderView.getVisiableHeight());  
  191.         if (mEnablePullRefresh && !mPullRefreshing) {// 未处于刷新状态,更新箭头  
  192.             if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {  
  193.                 mHeaderView.setState(XListViewHeader.STATE_READY);  
  194.             } else {  
  195.                 mHeaderView.setState(XListViewHeader.STATE_NORMAL);  
  196.             }  
  197.         }  
  198.         setSelection(0); // scroll to top each time  
  199.     }  
  200.   
  201.     /** 
  202.      * reset header view's height. 
  203.      */  
  204.     private void resetHeaderHeight() {  
  205.         int height = mHeaderView.getVisiableHeight();  
  206.         if (height == 0// not visible.  
  207.             return;  
  208.         // refreshing and header isn't shown fully. do nothing.  
  209.         if (mPullRefreshing && height <= mHeaderViewHeight) {  
  210.             return;  
  211.         }  
  212.         int finalHeight = 0// default: scroll back to dismiss header.  
  213.         // is refreshing, just scroll back to show all the header.  
  214.         if (mPullRefreshing && height > mHeaderViewHeight) {  
  215.             finalHeight = mHeaderViewHeight;  
  216.         }  
  217.         mScrollBack = SCROLLBACK_HEADER;  
  218.         mScroller.startScroll(0, height, 0, finalHeight - height,  
  219.                 SCROLL_DURATION);  
  220.         // trigger computeScroll  
  221.         invalidate();  
  222.     }  
  223.   
  224.     private void updateFooterHeight(float delta) {  
  225.         int height = mFooterView.getBottomMargin() + (int) delta;  
  226.         if (mEnablePullLoad && !mPullLoading) {  
  227.             if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load  
  228.                                                     // more.  
  229.                 mFooterView.setState(XListViewFooter.STATE_READY);  
  230.             } else {  
  231.                 mFooterView.setState(XListViewFooter.STATE_NORMAL);  
  232.             }  
  233.         }  
  234.         mFooterView.setBottomMargin(height);  
  235.   
  236. //      setSelection(mTotalItemCount - 1); // scroll to bottom  
  237.     }  
  238.   
  239.     private void resetFooterHeight() {  
  240.         int bottomMargin = mFooterView.getBottomMargin();  
  241.         if (bottomMargin > 0) {  
  242.             mScrollBack = SCROLLBACK_FOOTER;  
  243.             mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,  
  244.                     SCROLL_DURATION);  
  245.             invalidate();  
  246.         }  
  247.     }  
  248.   
  249.     private void startLoadMore() {  
  250.         mPullLoading = true;  
  251.         mFooterView.setState(XListViewFooter.STATE_LOADING);  
  252.         if (mListViewListener != null) {  
  253.             mListViewListener.onLoadMore();  
  254.         }  
  255.     }  
  256.   
  257.     @Override  
  258.     public boolean onTouchEvent(MotionEvent ev) {  
  259.         if (mLastY == -1) {  
  260.             mLastY = ev.getRawY();  
  261.         }  
  262.   
  263.         switch (ev.getAction()) {  
  264.         case MotionEvent.ACTION_DOWN:  
  265.             mLastY = ev.getRawY();  
  266.             break;  
  267.         case MotionEvent.ACTION_MOVE:  
  268.             final float deltaY = ev.getRawY() - mLastY;  
  269.             mLastY = ev.getRawY();  
  270.             if (getFirstVisiblePosition() == 0  
  271.                     && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {  
  272.                 // the first item is showing, header has shown or pull down.  
  273.                 updateHeaderHeight(deltaY / OFFSET_RADIO);  
  274.                 invokeOnScrolling();  
  275.             } else if (getLastVisiblePosition() == mTotalItemCount - 1  
  276.                     && (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {  
  277.                 // last item, already pulled up or want to pull up.  
  278.                 updateFooterHeight(-deltaY / OFFSET_RADIO);  
  279.             }  
  280.             break;  
  281.         default:  
  282.             mLastY = -1// reset  
  283.             if (getFirstVisiblePosition() == 0) {  
  284.                 // invoke refresh  
  285.                 if (mEnablePullRefresh  
  286.                         && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {  
  287.                     mPullRefreshing = true;  
  288.                     mHeaderView.setState(XListViewHeader.STATE_REFRESHING);  
  289.                     if (mListViewListener != null) {  
  290.                         mListViewListener.onRefresh();  
  291.                     }  
  292.                 }  
  293.                 resetHeaderHeight();  
  294.             } else if (getLastVisiblePosition() == mTotalItemCount - 1) {  
  295.                 // invoke load more.  
  296.                 if (mEnablePullLoad  
  297.                         && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {  
  298.                     startLoadMore();  
  299.                 }  
  300.                 resetFooterHeight();  
  301.             }  
  302.             break;  
  303.         }  
  304.         return super.onTouchEvent(ev);  
  305.     }  
  306.   
  307.     @Override  
  308.     public void computeScroll() {  
  309.         if (mScroller.computeScrollOffset()) {  
  310.             if (mScrollBack == SCROLLBACK_HEADER) {  
  311.                 mHeaderView.setVisiableHeight(mScroller.getCurrY());  
  312.             } else {  
  313.                 mFooterView.setBottomMargin(mScroller.getCurrY());  
  314.             }  
  315.             postInvalidate();  
  316.             invokeOnScrolling();  
  317.         }  
  318.         super.computeScroll();  
  319.     }  
  320.   
  321.     @Override  
  322.     public void setOnScrollListener(OnScrollListener l) {  
  323.         mScrollListener = l;  
  324.     }  
  325.   
  326.     @Override  
  327.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  328.         if (mScrollListener != null) {  
  329.             mScrollListener.onScrollStateChanged(view, scrollState);  
  330.         }  
  331.     }  
  332.   
  333.     @Override  
  334.     public void onScroll(AbsListView view, int firstVisibleItem,  
  335.             int visibleItemCount, int totalItemCount) {  
  336.         // send to user's listener  
  337.         mTotalItemCount = totalItemCount;  
  338.         if (mScrollListener != null) {  
  339.             mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,  
  340.                     totalItemCount);  
  341.         }  
  342.     }  
  343.   
  344.     public void setXListViewListener(IXListViewListener l) {  
  345.         mListViewListener = l;  
  346.     }  
  347.   
  348.     /** 
  349.      * you can listen ListView.OnScrollListener or this one. it will invoke 
  350.      * onXScrolling when header/footer scroll back. 
  351.      */  
  352.     public interface OnXScrollListener extends OnScrollListener {  
  353.         public void onXScrolling(View view);  
  354.     }  
  355.   
  356.     /** 
  357.      * implements this interface to get refresh/load more event. 
  358.      */  
  359.     public interface IXListViewListener {  
  360.         public void onRefresh();  
  361.         public void onLoadMore();  
  362.     }  
  363. }  

XListViewActivity.java

[java]  view plain copy
  1. package com.example.listviewrefresh;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.widget.ArrayAdapter;  
  9.   
  10. import com.example.listviewrefresh.XListView.IXListViewListener;  
  11.   
  12. public class XListViewActivity extends Activity implements IXListViewListener {  
  13.     private XListView mListView;  
  14.     private ArrayAdapter<String> mAdapter;  
  15.     private ArrayList<String> items = new ArrayList<String>();  
  16.     private Handler mHandler;  
  17.     private int start = 0;  
  18.     private static int refreshCnt = 0;  
  19.     /** Called when the activity is first created. */  
  20.     @Override  
  21.     public void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.main);  
  24.         geneItems();  
  25.         mListView = (XListView) findViewById(R.id.xListView);  
  26.         mListView.setPullLoadEnable(true);  
  27.         mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, items);  
  28.         mListView.setAdapter(mAdapter);  
  29. //      mListView.setPullLoadEnable(false);  
  30. //      mListView.setPullRefreshEnable(false);  
  31.         mListView.setXListViewListener(this);  
  32.         mHandler = new Handler();  
  33.     }  
  34.   
  35.     private void geneItems() {  
  36.         for (int i = 0; i != 20; ++i) {  
  37.             items.add("refresh cnt " + (++start));  
  38.         }  
  39.     }  
  40.   
  41.     private void onLoad() {  
  42.         mListView.stopRefresh();  
  43.         mListView.stopLoadMore();  
  44.         mListView.setRefreshTime("1233456689");  
  45.     }  
  46.       
  47.     @Override  
  48.     public void onRefresh() {  
  49.         mHandler.postDelayed(new Runnable() {  
  50.             @Override  
  51.             public void run() {  
  52.                 start = ++refreshCnt;  
  53.                 items.clear();  
  54.                 geneItems();  
  55.                 // mAdapter.notifyDataSetChanged();  
  56.                 mAdapter = new ArrayAdapter<String>(XListViewActivity.this, R.layout.list_item, items);  
  57.                 mListView.setAdapter(mAdapter);  
  58.                 onLoad();  
  59.             }  
  60.         }, 2000);  
  61.     }  
  62.   
  63.     @Override  
  64.     public void onLoadMore() {  
  65.         mHandler.postDelayed(new Runnable() {  
  66.             @Override  
  67.             public void run() {  
  68.                 geneItems();  
  69.                 mAdapter.notifyDataSetChanged();  
  70.                 onLoad();  
  71.             }  
  72.         }, 2000);  
  73.     }  
  74.   
  75. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值