上拉下拉刷新,支持ListView,GridView,ScrollView

转载地址:http://gundumw100.iteye.com/blog/1764763

网上很多这样的效果都是继承某个具体的AdapterView或ScrollView,这样很不通用,如果继承自一个ViewGroup(比如LinearLayout),那么任何放在其中的子view都有上拉下拉刷新,那不就完美了? 
不废话,上代码: 
Java代码   收藏代码
  1. import android.content.Context;  
  2. import android.util.AttributeSet;  
  3. import android.view.LayoutInflater;  
  4. import android.view.MotionEvent;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7. import android.view.animation.LinearInterpolator;  
  8. import android.view.animation.RotateAnimation;  
  9. import android.widget.AdapterView;  
  10. import android.widget.ImageView;  
  11. import android.widget.LinearLayout;  
  12. import android.widget.ProgressBar;  
  13. import android.widget.ScrollView;  
  14. import android.widget.TextView;  
  15.   
  16.   
  17. public class PullToRefreshView extends LinearLayout {  
  18. //  private static final String TAG = "PullToRefreshView";  
  19.     // refresh states  
  20.     private static final int PULL_TO_REFRESH = 2;  
  21.     private static final int RELEASE_TO_REFRESH = 3;  
  22.     private static final int REFRESHING = 4;  
  23.     // pull state  
  24.     private static final int PULL_UP_STATE = 0;  
  25.     private static final int PULL_DOWN_STATE = 1;  
  26.     /** 
  27.      * last y 
  28.      */  
  29.     private int mLastMotionY;  
  30.     /** 
  31.      * lock 
  32.      */  
  33. //  private boolean mLock;  
  34.     /** 
  35.      * header view 
  36.      */  
  37.     private View mHeaderView;  
  38.     /** 
  39.      * footer view 
  40.      */  
  41.     private View mFooterView;  
  42.     /** 
  43.      * list or grid 
  44.      */  
  45.     private AdapterView<?> mAdapterView;  
  46.     /** 
  47.      * scrollview 
  48.      */  
  49.     private ScrollView mScrollView;  
  50.     /** 
  51.      * header view height 
  52.      */  
  53.     private int mHeaderViewHeight;  
  54.     /** 
  55.      * footer view height 
  56.      */  
  57.     private int mFooterViewHeight;  
  58.     /** 
  59.      * header view image 
  60.      */  
  61.     private ImageView mHeaderImageView;  
  62.     /** 
  63.      * footer view image 
  64.      */  
  65.     private ImageView mFooterImageView;  
  66.     /** 
  67.      * header tip text 
  68.      */  
  69.     private TextView mHeaderTextView;  
  70.     /** 
  71.      * footer tip text 
  72.      */  
  73.     private TextView mFooterTextView;  
  74.     /** 
  75.      * header refresh time 
  76.      */  
  77.     private TextView mHeaderUpdateTextView;  
  78.     /** 
  79.      * footer refresh time 
  80.      */  
  81.     // private TextView mFooterUpdateTextView;  
  82.     /** 
  83.      * header progress bar 
  84.      */  
  85.     private ProgressBar mHeaderProgressBar;  
  86.     /** 
  87.      * footer progress bar 
  88.      */  
  89.     private ProgressBar mFooterProgressBar;  
  90.     /** 
  91.      * layout inflater 
  92.      */  
  93.     private LayoutInflater mInflater;  
  94.     /** 
  95.      * header view current state 
  96.      */  
  97.     private int mHeaderState;  
  98.     /** 
  99.      * footer view current state 
  100.      */  
  101.     private int mFooterState;  
  102.     /** 
  103.      * pull state,pull up or pull down;PULL_UP_STATE or PULL_DOWN_STATE 
  104.      */  
  105.     private int mPullState;  
  106.     /** 
  107.      * 变为向下的箭头,改变箭头方向 
  108.      */  
  109.     private RotateAnimation mFlipAnimation;  
  110.     /** 
  111.      * 变为逆向的箭头,旋转 
  112.      */  
  113.     private RotateAnimation mReverseFlipAnimation;  
  114.     /** 
  115.      * footer refresh listener 
  116.      */  
  117.     private OnFooterRefreshListener mOnFooterRefreshListener;  
  118.     /** 
  119.      * footer refresh listener 
  120.      */  
  121.     private OnHeaderRefreshListener mOnHeaderRefreshListener;  
  122.     /** 
  123.      * last update time 
  124.      */  
  125. //  private String mLastUpdateTime;  
  126.   
  127.     public PullToRefreshView(Context context, AttributeSet attrs) {  
  128.         super(context, attrs);  
  129.         init();  
  130.     }  
  131.   
  132.     public PullToRefreshView(Context context) {  
  133.         super(context);  
  134.         init();  
  135.     }  
  136.   
  137.     /** 
  138.      * init 
  139.      *  
  140.      * @param context 
  141.      */  
  142.     private void init() {  
  143.         //需要设置成vertical  
  144.         setOrientation(LinearLayout.VERTICAL);  
  145.         // Load all of the animations we need in code rather than through XML  
  146.         mFlipAnimation = new RotateAnimation(0, -180,  
  147.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  148.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  149.         mFlipAnimation.setInterpolator(new LinearInterpolator());  
  150.         mFlipAnimation.setDuration(250);  
  151.         mFlipAnimation.setFillAfter(true);  
  152.         mReverseFlipAnimation = new RotateAnimation(-1800,  
  153.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  154.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  155.         mReverseFlipAnimation.setInterpolator(new LinearInterpolator());  
  156.         mReverseFlipAnimation.setDuration(250);  
  157.         mReverseFlipAnimation.setFillAfter(true);  
  158.   
  159.         mInflater = LayoutInflater.from(getContext());  
  160.         // header view 在此添加,保证是第一个添加到linearlayout的最上端  
  161.         addHeaderView();  
  162.     }  
  163.   
  164.     private void addHeaderView() {  
  165.         // header view  
  166.         mHeaderView = mInflater.inflate(R.layout.refresh_header, thisfalse);  
  167.   
  168.         mHeaderImageView = (ImageView) mHeaderView  
  169.                 .findViewById(R.id.pull_to_refresh_image);  
  170.         mHeaderTextView = (TextView) mHeaderView  
  171.                 .findViewById(R.id.pull_to_refresh_text);  
  172.         mHeaderUpdateTextView = (TextView) mHeaderView  
  173.                 .findViewById(R.id.pull_to_refresh_updated_at);  
  174.         mHeaderProgressBar = (ProgressBar) mHeaderView  
  175.                 .findViewById(R.id.pull_to_refresh_progress);  
  176.         // header layout  
  177.         measureView(mHeaderView);  
  178.         mHeaderViewHeight = mHeaderView.getMeasuredHeight();  
  179.         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,  
  180.                 mHeaderViewHeight);  
  181.         // 设置topMargin的值为负的header View高度,即将其隐藏在最上方  
  182.         params.topMargin = -(mHeaderViewHeight);  
  183.         // mHeaderView.setLayoutParams(params1);  
  184.         addView(mHeaderView, params);  
  185.   
  186.     }  
  187.   
  188.     private void addFooterView() {  
  189.         // footer view  
  190.         mFooterView = mInflater.inflate(R.layout.refresh_footer, thisfalse);  
  191.         mFooterImageView = (ImageView) mFooterView  
  192.                 .findViewById(R.id.pull_to_load_image);  
  193.         mFooterTextView = (TextView) mFooterView  
  194.                 .findViewById(R.id.pull_to_load_text);  
  195.         mFooterProgressBar = (ProgressBar) mFooterView  
  196.                 .findViewById(R.id.pull_to_load_progress);  
  197.         // footer layout  
  198.         measureView(mFooterView);  
  199.         mFooterViewHeight = mFooterView.getMeasuredHeight();  
  200.         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,  
  201.                 mFooterViewHeight);  
  202.         // int top = getHeight();  
  203.         // params.topMargin  
  204.         // =getHeight();//在这里getHeight()==0,但在onInterceptTouchEvent()方法里getHeight()已经有值了,不再是0;  
  205.         // getHeight()什么时候会赋值,稍候再研究一下  
  206.         // 由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏  
  207.         addView(mFooterView, params);  
  208.     }  
  209.   
  210.     @Override  
  211.     protected void onFinishInflate() {  
  212.         super.onFinishInflate();  
  213.         // footer view 在此添加保证添加到linearlayout中的最后  
  214.         addFooterView();  
  215.         initContentAdapterView();  
  216.     }  
  217.   
  218.     /** 
  219.      * init AdapterView like ListView,GridView and so on;or init ScrollView 
  220.      *  
  221.      */  
  222.     private void initContentAdapterView() {  
  223.         int count = getChildCount();  
  224.         if (count < 3) {  
  225.             throw new IllegalArgumentException(  
  226.                     "This layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");  
  227.         }  
  228.         View view = null;  
  229.         for (int i = 0; i < count - 1; ++i) {  
  230.             view = getChildAt(i);  
  231.             if (view instanceof AdapterView<?>) {  
  232.                 mAdapterView = (AdapterView<?>) view;  
  233.             }  
  234.             if (view instanceof ScrollView) {  
  235.                 // finish later  
  236.                 mScrollView = (ScrollView) view;  
  237.             }  
  238.         }  
  239.         if (mAdapterView == null && mScrollView == null) {  
  240.             throw new IllegalArgumentException(  
  241.                     "must contain a AdapterView or ScrollView in this layout!");  
  242.         }  
  243.     }  
  244.   
  245.     private void measureView(View child) {  
  246.         ViewGroup.LayoutParams p = child.getLayoutParams();  
  247.         if (p == null) {  
  248.             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,  
  249.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  250.         }  
  251.   
  252.         int childWidthSpec = ViewGroup.getChildMeasureSpec(00 + 0, p.width);  
  253.         int lpHeight = p.height;  
  254.         int childHeightSpec;  
  255.         if (lpHeight > 0) {  
  256.             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,  
  257.                     MeasureSpec.EXACTLY);  
  258.         } else {  
  259.             childHeightSpec = MeasureSpec.makeMeasureSpec(0,  
  260.                     MeasureSpec.UNSPECIFIED);  
  261.         }  
  262.         child.measure(childWidthSpec, childHeightSpec);  
  263.     }  
  264.   
  265.     @Override  
  266.     public boolean onInterceptTouchEvent(MotionEvent e) {  
  267.         int y = (int) e.getRawY();  
  268.         switch (e.getAction()) {  
  269.         case MotionEvent.ACTION_DOWN:  
  270.             // 首先拦截down事件,记录y坐标  
  271.             mLastMotionY = y;  
  272.             break;  
  273.         case MotionEvent.ACTION_MOVE:  
  274.             // deltaY > 0 是向下运动,< 0是向上运动  
  275.             int deltaY = y - mLastMotionY;  
  276.             if (isRefreshViewScroll(deltaY)) {  
  277.                 return true;  
  278.             }  
  279.             break;  
  280.         case MotionEvent.ACTION_UP:  
  281.         case MotionEvent.ACTION_CANCEL:  
  282.             break;  
  283.         }  
  284.         return false;  
  285.     }  
  286.   
  287.     /* 
  288.      * 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return 
  289.      * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理) 
  290.      */  
  291.     @Override  
  292.     public boolean onTouchEvent(MotionEvent event) {  
  293. //      if (mLock) {  
  294. //          return true;  
  295. //      }  
  296.         int y = (int) event.getRawY();  
  297.         switch (event.getAction()) {  
  298.         case MotionEvent.ACTION_DOWN:  
  299.             // onInterceptTouchEvent已经记录  
  300.             // mLastMotionY = y;  
  301.             break;  
  302.         case MotionEvent.ACTION_MOVE:  
  303.             int deltaY = y - mLastMotionY;  
  304.             if (mPullState == PULL_DOWN_STATE) {//执行下拉  
  305.                 headerPrepareToRefresh(deltaY);  
  306.                 // setHeaderPadding(-mHeaderViewHeight);  
  307.             } else if (mPullState == PULL_UP_STATE) {//执行上拉  
  308.                 footerPrepareToRefresh(deltaY);  
  309.             }  
  310.             mLastMotionY = y;  
  311.             break;  
  312.         case MotionEvent.ACTION_UP:  
  313.         case MotionEvent.ACTION_CANCEL:  
  314.             int topMargin = getHeaderTopMargin();  
  315.             if (mPullState == PULL_DOWN_STATE) {  
  316.                 if (topMargin >= 0) {  
  317.                     // 开始刷新  
  318.                     headerRefreshing();  
  319.                 } else {  
  320.                     // 还没有执行刷新,重新隐藏  
  321.                     setHeaderTopMargin(-mHeaderViewHeight);  
  322.                 }  
  323.             } else if (mPullState == PULL_UP_STATE) {  
  324.                 if (Math.abs(topMargin) >= mHeaderViewHeight  
  325.                         + mFooterViewHeight) {  
  326.                     // 开始执行footer 刷新  
  327.                     footerRefreshing();  
  328.                 } else {  
  329.                     // 还没有执行刷新,重新隐藏  
  330.                     setHeaderTopMargin(-mHeaderViewHeight);  
  331.                 }  
  332.             }  
  333.             break;  
  334.         }  
  335.         return super.onTouchEvent(event);  
  336.     }  
  337.   
  338.     /** 
  339.      * 是否应该到了父View,即PullToRefreshView滑动 
  340.      *  
  341.      * @param deltaY 
  342.      *            , deltaY > 0 是向下运动,< 0是向上运动 
  343.      * @return 
  344.      */  
  345.     private boolean isRefreshViewScroll(int deltaY) {  
  346.         if (mHeaderState == REFRESHING || mFooterState == REFRESHING) {  
  347.             return false;  
  348.         }  
  349.         //对于ListView和GridView  
  350.         if (mAdapterView != null) {  
  351.             // 子view(ListView or GridView)滑动到最顶端  
  352.             if (deltaY > 0) {  
  353.   
  354.                 View child = mAdapterView.getChildAt(0);  
  355.                 if (child == null) {  
  356.                     // 如果mAdapterView中没有数据,不拦截  
  357.                     return false;  
  358.                 }  
  359.                 if (mAdapterView.getFirstVisiblePosition() == 0  
  360.                         && child.getTop() == 0) {  
  361.                     mPullState = PULL_DOWN_STATE;  
  362.                     return true;  
  363.                 }  
  364.                 int top = child.getTop();  
  365.                 int padding = mAdapterView.getPaddingTop();  
  366.                 if (mAdapterView.getFirstVisiblePosition() == 0  
  367.                         && Math.abs(top - padding) <= 8) {//这里之前用3可以判断,但现在不行,还没找到原因  
  368.                     mPullState = PULL_DOWN_STATE;  
  369.                     return true;  
  370.                 }  
  371.   
  372.             } else if (deltaY < 0) {  
  373.                 View lastChild = mAdapterView.getChildAt(mAdapterView  
  374.                         .getChildCount() - 1);  
  375.                 if (lastChild == null) {  
  376.                     // 如果mAdapterView中没有数据,不拦截  
  377.                     return false;  
  378.                 }  
  379.                 // 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,  
  380.                 // 等于父View的高度说明mAdapterView已经滑动到最后  
  381.                 if (lastChild.getBottom() <= getHeight()  
  382.                         && mAdapterView.getLastVisiblePosition() == mAdapterView  
  383.                                 .getCount() - 1) {  
  384.                     mPullState = PULL_UP_STATE;  
  385.                     return true;  
  386.                 }  
  387.             }  
  388.         }  
  389.         // 对于ScrollView  
  390.         if (mScrollView != null) {  
  391.             // 子scroll view滑动到最顶端  
  392.             View child = mScrollView.getChildAt(0);  
  393.             if (deltaY > 0 && mScrollView.getScrollY() == 0) {  
  394.                 mPullState = PULL_DOWN_STATE;  
  395.                 return true;  
  396.             } else if (deltaY < 0  
  397.                     && child.getMeasuredHeight() <= getHeight()  
  398.                             + mScrollView.getScrollY()) {  
  399.                 mPullState = PULL_UP_STATE;  
  400.                 return true;  
  401.             }  
  402.         }  
  403.         return false;  
  404.     }  
  405.   
  406.     /** 
  407.      * header 准备刷新,手指移动过程,还没有释放 
  408.      *  
  409.      * @param deltaY 
  410.      *            ,手指滑动的距离 
  411.      */  
  412.     private void headerPrepareToRefresh(int deltaY) {  
  413.         int newTopMargin = changingHeaderViewTopMargin(deltaY);  
  414.         // 当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态  
  415.         if (newTopMargin >= 0 && mHeaderState != RELEASE_TO_REFRESH) {  
  416.             mHeaderTextView.setText(R.string.pull_to_refresh_release_label);  
  417.             mHeaderUpdateTextView.setVisibility(View.VISIBLE);  
  418.             mHeaderImageView.clearAnimation();  
  419.             mHeaderImageView.startAnimation(mFlipAnimation);  
  420.             mHeaderState = RELEASE_TO_REFRESH;  
  421.         } else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {// 拖动时没有释放  
  422.             mHeaderImageView.clearAnimation();  
  423.             mHeaderImageView.startAnimation(mFlipAnimation);  
  424.             // mHeaderImageView.  
  425.             mHeaderTextView.setText(R.string.pull_to_refresh_pull_label);  
  426.             mHeaderState = PULL_TO_REFRESH;  
  427.         }  
  428.     }  
  429.   
  430.     /** 
  431.      * footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view 
  432.      * 高度是一样,都是通过修改header view的topmargin的值来达到 
  433.      *  
  434.      * @param deltaY 
  435.      *            ,手指滑动的距离 
  436.      */  
  437.     private void footerPrepareToRefresh(int deltaY) {  
  438.         int newTopMargin = changingHeaderViewTopMargin(deltaY);  
  439.         // 如果header view topMargin 的绝对值大于或等于header + footer 的高度  
  440.         // 说明footer view 完全显示出来了,修改footer view 的提示状态  
  441.         if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight)  
  442.                 && mFooterState != RELEASE_TO_REFRESH) {  
  443.             mFooterTextView  
  444.                     .setText(R.string.pull_to_refresh_footer_release_label);  
  445.             mFooterImageView.clearAnimation();  
  446.             mFooterImageView.startAnimation(mFlipAnimation);  
  447.             mFooterState = RELEASE_TO_REFRESH;  
  448.         } else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {  
  449.             mFooterImageView.clearAnimation();  
  450.             mFooterImageView.startAnimation(mFlipAnimation);  
  451.             mFooterTextView.setText(R.string.pull_to_refresh_footer_pull_label);  
  452.             mFooterState = PULL_TO_REFRESH;  
  453.         }  
  454.     }  
  455.   
  456.     /** 
  457.      * 修改Header view top margin的值 
  458.      *  
  459.      * @param deltaY 
  460.      */  
  461.     private int changingHeaderViewTopMargin(int deltaY) {  
  462.         LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();  
  463.         float newTopMargin = params.topMargin + deltaY * 0.3f;  
  464.         //这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了,感谢网友yufengzungzhe的指出  
  465.         //表示如果是在上拉后一段距离,然后直接下拉  
  466.         if(deltaY>0&&mPullState == PULL_UP_STATE&&Math.abs(params.topMargin) <= mHeaderViewHeight){  
  467.             return params.topMargin;  
  468.         }  
  469.         //同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug  
  470.         if(deltaY<0&&mPullState == PULL_DOWN_STATE&&Math.abs(params.topMargin)>=mHeaderViewHeight){  
  471.             return params.topMargin;  
  472.         }  
  473.         params.topMargin = (int) newTopMargin;  
  474.         mHeaderView.setLayoutParams(params);  
  475.         invalidate();  
  476.         return params.topMargin;  
  477.     }  
  478.   
  479.     /** 
  480.      * header refreshing 
  481.      *  
  482.      */  
  483.     private void headerRefreshing() {  
  484.         mHeaderState = REFRESHING;  
  485.         setHeaderTopMargin(0);  
  486.         mHeaderImageView.setVisibility(View.GONE);  
  487.         mHeaderImageView.clearAnimation();  
  488.         mHeaderImageView.setImageDrawable(null);  
  489.         mHeaderProgressBar.setVisibility(View.VISIBLE);  
  490.         mHeaderTextView.setText(R.string.pull_to_refresh_refreshing_label);  
  491.         if (mOnHeaderRefreshListener != null) {  
  492.             mOnHeaderRefreshListener.onHeaderRefresh(this);  
  493.         }  
  494.     }  
  495.   
  496.     /** 
  497.      * footer refreshing 
  498.      *  
  499.      */  
  500.     private void footerRefreshing() {  
  501.         mFooterState = REFRESHING;  
  502.         int top = mHeaderViewHeight + mFooterViewHeight;  
  503.         setHeaderTopMargin(-top);  
  504.         mFooterImageView.setVisibility(View.GONE);  
  505.         mFooterImageView.clearAnimation();  
  506.         mFooterImageView.setImageDrawable(null);  
  507.         mFooterProgressBar.setVisibility(View.VISIBLE);  
  508.         mFooterTextView  
  509.                 .setText(R.string.pull_to_refresh_footer_refreshing_label);  
  510.         if (mOnFooterRefreshListener != null) {  
  511.             mOnFooterRefreshListener.onFooterRefresh(this);  
  512.         }  
  513.     }  
  514.   
  515.     /** 
  516.      * 设置header view 的topMargin的值 
  517.      *  
  518.      * @param topMargin 
  519.      *            ,为0时,说明header view 刚好完全显示出来; 为-mHeaderViewHeight时,说明完全隐藏了 
  520.      */  
  521.     private void setHeaderTopMargin(int topMargin) {  
  522.         LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();  
  523.         params.topMargin = topMargin;  
  524.         mHeaderView.setLayoutParams(params);  
  525.         invalidate();  
  526.     }  
  527.   
  528.     /** 
  529.      * header view 完成更新后恢复初始状态 
  530.      *  
  531.      */  
  532.     public void onHeaderRefreshComplete() {  
  533.         setHeaderTopMargin(-mHeaderViewHeight);  
  534.         mHeaderImageView.setVisibility(View.VISIBLE);  
  535.         mHeaderImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);  
  536.         mHeaderTextView.setText(R.string.pull_to_refresh_pull_label);  
  537.         mHeaderProgressBar.setVisibility(View.GONE);  
  538.         // mHeaderUpdateTextView.setText("");  
  539.         mHeaderState = PULL_TO_REFRESH;  
  540.     }  
  541.   
  542.     /** 
  543.      * Resets the list to a normal state after a refresh. 
  544.      *  
  545.      * @param lastUpdated 
  546.      *            Last updated at. 
  547.      */  
  548.     public void onHeaderRefreshComplete(CharSequence lastUpdated) {  
  549.         setLastUpdated(lastUpdated);  
  550.         onHeaderRefreshComplete();  
  551.     }  
  552.   
  553.     /** 
  554.      * footer view 完成更新后恢复初始状态 
  555.      */  
  556.     public void onFooterRefreshComplete() {  
  557.         setHeaderTopMargin(-mHeaderViewHeight);  
  558.         mFooterImageView.setVisibility(View.VISIBLE);  
  559.         mFooterImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow_up);  
  560.         mFooterTextView.setText(R.string.pull_to_refresh_footer_pull_label);  
  561.         mFooterProgressBar.setVisibility(View.GONE);  
  562.         // mHeaderUpdateTextView.setText("");  
  563.         mFooterState = PULL_TO_REFRESH;  
  564.     }  
  565.   
  566.     /** 
  567.      * Set a text to represent when the list was last updated. 
  568.      *  
  569.      * @param lastUpdated 
  570.      *            Last updated at. 
  571.      */  
  572.     public void setLastUpdated(CharSequence lastUpdated) {  
  573.         if (lastUpdated != null) {  
  574.             mHeaderUpdateTextView.setVisibility(View.VISIBLE);  
  575.             mHeaderUpdateTextView.setText(lastUpdated);  
  576.         } else {  
  577.             mHeaderUpdateTextView.setVisibility(View.GONE);  
  578.         }  
  579.     }  
  580.   
  581.     /** 
  582.      * 获取当前header view 的topMargin 
  583.      *  
  584.      */  
  585.     private int getHeaderTopMargin() {  
  586.         LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();  
  587.         return params.topMargin;  
  588.     }  
  589.   
  590. //  /**  
  591. //   * lock  
  592. //   *   
  593. //   */  
  594. //  private void lock() {  
  595. //      mLock = true;  
  596. //  }  
  597. //  
  598. //  /**  
  599. //   * unlock  
  600. //   *   
  601. //   */  
  602. //  private void unlock() {  
  603. //      mLock = false;  
  604. //  }  
  605.   
  606.     /** 
  607.      * set headerRefreshListener 
  608.      *  
  609.      * @param headerRefreshListener 
  610.      */  
  611.     public void setOnHeaderRefreshListener(  
  612.             OnHeaderRefreshListener headerRefreshListener) {  
  613.         mOnHeaderRefreshListener = headerRefreshListener;  
  614.     }  
  615.   
  616.     public void setOnFooterRefreshListener(  
  617.             OnFooterRefreshListener footerRefreshListener) {  
  618.         mOnFooterRefreshListener = footerRefreshListener;  
  619.     }  
  620.   
  621.     /** 
  622.      * Interface definition for a callback to be invoked when list/grid footer 
  623.      * view should be refreshed. 
  624.      */  
  625.     public interface OnFooterRefreshListener {  
  626.         public void onFooterRefresh(PullToRefreshView view);  
  627.     }  
  628.   
  629.     /** 
  630.      * Interface definition for a callback to be invoked when list/grid header 
  631.      * view should be refreshed. 
  632.      */  
  633.     public interface OnHeaderRefreshListener {  
  634.         public void onHeaderRefresh(PullToRefreshView view);  
  635.     }  
  636. }  


用法: 
Java代码   收藏代码
  1. import java.util.Date;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.widget.GridView;  
  6.   
  7. import com.example.pulltorefresh.PullToRefreshView.OnFooterRefreshListener;  
  8. import com.example.pulltorefresh.PullToRefreshView.OnHeaderRefreshListener;  
  9.   
  10.   
  11. public class TestGridView extends Activity implements OnHeaderRefreshListener,OnFooterRefreshListener{  
  12.     PullToRefreshView mPullToRefreshView;  
  13.     GridView mGridView;  
  14.     @Override  
  15.     protected void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.test_gridview);  
  18.           
  19.         mPullToRefreshView = (PullToRefreshView)findViewById(R.id.main_pull_refresh_view);  
  20.         mGridView = (GridView)findViewById(R.id.gridview);  
  21.         mGridView.setAdapter(new DataAdapter(this));  
  22.         mPullToRefreshView.setOnHeaderRefreshListener(this);  
  23.         mPullToRefreshView.setOnFooterRefreshListener(this);  
  24.         mPullToRefreshView.setLastUpdated(new Date().toLocaleString());  
  25.           
  26.     }  
  27.     @Override  
  28.     public void onFooterRefresh(PullToRefreshView view) {  
  29.         mPullToRefreshView.postDelayed(new Runnable() {  
  30.               
  31.             @Override  
  32.             public void run() {  
  33.                 mPullToRefreshView.onFooterRefreshComplete();  
  34.             }  
  35.         },1000);  
  36.     }  
  37.     @Override  
  38.     public void onHeaderRefresh(PullToRefreshView view) {  
  39.         mPullToRefreshView.postDelayed(new Runnable() {  
  40.               
  41.             @Override  
  42.             public void run() {  
  43.                 mPullToRefreshView.onHeaderRefreshComplete("更新于:"+new Date().toLocaleString());  
  44. //              mPullToRefreshView.onHeaderRefreshComplete();  
  45.             }  
  46.         },1000);  
  47.           
  48.     }  
  49. }  


具体的看附件 


官方下拉刷新控件SwipeRefreshLayout的使用 
http://www.cnblogs.com/kross/p/3647498.html 


一个顺滑又漂亮的Android下拉刷新与加载更多列表组件 
https://github.com/zarics/ZrcListView 

Android-PullToRefresh 
https://github.com/chrisbanes/Android-PullToRefresh
  • PullToRefresh.zip (743.8 KB)
  • 下载次数: 882
  • master_3_.zip (1.6 MB)
  • 描述: ZrcListView
  • 下载次数: 19

你可能感兴趣的:(上拉下拉刷新,支持ListView,GridView,ScrollView)