在上一篇文章《有阻尼下拉刷新列表的实现》中,我解析了如何基于重载dispatchDraw方法重画子View和重载onTouchEvent方法监控受试来实现下拉刷新列表,而在这篇文章中,我将会基于上一篇文章介绍的技术,在下拉刷新列表PullToRefreshListVIew的基础上,加上有阻尼上拉刷新功能。上一篇文章《有阻尼下拉刷新列表的实现》的链接如下。

http://blog.csdn.net/ivan_zgj/article/details/50664780

        好,我们还是先来看看效果。


1. 通过onScrollListener监控listVIew是否滚动到底部

        在PullToRefreshListView中,我们通过onScrollListener回调来监控PullToRefreshListView是否已经滚动到顶部,当时的代码是这样的:

    setOnScrollListener(new OnScrollListener() {          @Override          public void onScrollStateChanged(AbsListView view, int scrollState) {                }                @Override          public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {              // 没有子view的时候(没有数据,或者被拉到看不到子view),意味着该listView滚动到顶部              if (getChildCount() == 0) {                  isTop = true;                  return;              }              if (firstVisibleItem == 0) {                  View firstView = getChildAt(0);                  if (firstView.getTop() + distanceY >= 0) {                      // 第一个view可见且其相对parent(该listView)的顶部距离大于等于0,意味着该listView也是滚动到顶部                      isTop = true;                      return;                  }              }              isTop = false;          }      });    
         当时我们通过判断firstVisibleItem==0以及第一个子View是否完全可见,从而确定PullToRefreshListView是否滚动到顶部。现在,我们加入以下代码来判断PullToRefreshListView是否滚动到底部。

                if (firstVisibleItem + visibleItemCount == totalItemCount) {                    View firstView = getChildAt(visibleItemCount - 1);                    if (firstView.getBottom() + distanceY <= getHeight()) {                        // 最后一个view可见且其相对parent(该listView)的底部距离小于等于listView高度,意味着该listView也是滚动到底部                        isBottom = true;                        return;                    }                }                isBottom = false;
        在onScroll方法中,fisrstVisibleItem是指列表当前可见的第一个子View在其adapter中的position,而visibleItemCount是指可见的子View的个数,totalItemCount是指adapter总共有多少个View。因此,我们可以很容易得出结论,当:
firstVisibleItem + visibleItemCount == totalItemCount
成立时,PullToRefreshListView就已经滚动到底部了。


2. 监控滑动手势使listView进入上拉状态

        在PullToRefreshListView中,我们通过重载onTouchEvent方法来监控用户手势,从而判断PullToRefreshListView是否要进行下拉,当时的代码是这样的:

@Override  public boolean onTouchEvent(MotionEvent ev) {      if (lastAction == -1 && ev.getActionMasked() == MotionEvent.ACTION_DOWN) {          // 按下的时候          lastAction = MotionEvent.ACTION_DOWN;          cancelAnimating();          L.d(TAG, "touch down");      } else if (lastAction == MotionEvent.ACTION_MOVE && ev.getActionMasked() == MotionEvent.ACTION_UP) {          // 放开手指,开始回滚          isPulling = false;          lastAction = -1;          startAnimating();          L.d(TAG, "touch up");      } else if (lastAction == MotionEvent.ACTION_DOWN) {          if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {              // 在按下手指的基础上,开始滑动              if (isTop && !isPulling) {                  // listView在顶部而且不处于下拉刷新状态,开始下拉                  pullStartY = ev.getY();                  lastAction = MotionEvent.ACTION_MOVE;                  isPulling = true;              }          }      } else if (lastAction == MotionEvent.ACTION_MOVE) {          if (isTop) {              // 下拉              distanceY = ev.getY() - pullStartY;              L.d(TAG, distanceY + "");              if (distanceY > 0) {                  distanceY = (float) (Math.exp(-ev.getY() / pullStartY / 40) * distanceY);                  // 在下拉状态时取消系统对move动作的响应,完全由本类响应                  ev.setAction(MotionEvent.ACTION_DOWN);              } else {                  distanceY = 0;                  // 在下拉过程中往上拉动该listView使得其回到顶部位置,则将该move动作交由系统进行响应                  ev.setAction(MotionEvent.ACTION_MOVE);              }          } else {              // 在下拉过程中往上拉动listView使listView往下滚动到其没有滚动到顶部,则取消其下拉状态,回到手指按下的初始状态              lastAction = MotionEvent.ACTION_DOWN;              isPulling = false;              distanceY = 0;          }      }      return super.onTouchEvent(ev);  } 

         现在,我们只需要在lastAction == MotionEvent.ACTION_MOVE判断里面,与isTop判断并列,再加一个判断。

            if (isBottom) {                // 上拉                configureHeader(false);                distanceY = ev.getY() - pullStartY;                L.d(TAG, distanceY + "");                if (distanceY < 0) {                    distanceY = (float) (Math.exp(-pullStartY / ev.getY() / 40) * distanceY);                    // 在上拉状态时取消系统对move动作的响应,完全由本类响应                    ev.setAction(MotionEvent.ACTION_DOWN);                } else {                    distanceY = 0;                    // 在上拉过程中往上拉动该listView使得其回到顶部位置,则将该move动作交由系统进行响应                    ev.setAction(MotionEvent.ACTION_MOVE);                }            }

        很明显,这个判断是在执行这样一个动作,如果PullToRefreshListView已经滚动到底部,那么就根据用户手指滑动的距离计算PullToRefreshListView上拉的距离,这一段代码与处理下拉的代码是基本一样的。

3. 重载dispatchDraw方法实现上拉

         在PullToRefreshListView的基础上,我们将重画下拉的子View的代码替换成以下代码。

            // 重画子view            int left = getPaddingLeft();            int top = getPaddingTop();            int bottom = getPaddingBottom();            canvas.save();            if (distanceY > 0) {                canvas.translate(left, top + distanceY);            } else {                canvas.translate(left, -bottom + distanceY);            }            for (int i=0;i

        这里只需要注意下拉和上拉的时候canvas要translate的方向和距离的计算就可以了,原理在上一篇文章中已经解析过了,这里就不多说了。大家结合着看就好了。

4. 加上刷新头

        为了优化UI和给用户做出提示,我这次还加入刷新头,就是那个提示下拉刷新,释放以刷新blablabla的东西。同样的,我也是在dispatchDraw方法里面实现的。具体代码如下。

            canvas.save();            // 画刷新头            View header;            if (distanceY > 0) {                int whereToLoad = dp2px(onLoadCallBack.whereToLoad(true));                if (distanceY > whereToLoad) {                    topRefreshHeaderView.setText(HeaderView.STATE_CAN_RELEASE);                    topRefreshHeaderView.setIcon(HeaderView.STATE_CAN_RELEASE);                } else if (distanceY < whereToLoad) {                    topRefreshHeaderView.setText(HeaderView.STATE_PULLING_DOWN);                    topRefreshHeaderView.setIcon(HeaderView.STATE_PULLING_DOWN);                }                header = topRefreshHeaderView.getView();                canvas.translate(left, top + distanceY - header.getHeight() - offset);            } else {                int whereToLoad = dp2px(onLoadCallBack.whereToLoad(false));                if (-distanceY > whereToLoad) {                    bottomRefreshHeaderView.setText(HeaderView.STATE_CAN_RELEASE);                    bottomRefreshHeaderView.setIcon(HeaderView.STATE_CAN_RELEASE);                } else if (-distanceY < whereToLoad) {                    bottomRefreshHeaderView.setText(HeaderView.STATE_PULLING_UP);                    bottomRefreshHeaderView.setIcon(HeaderView.STATE_PULLING_UP);                }                header = bottomRefreshHeaderView.getView();                canvas.translate(left, -bottom + distanceY + getHeight() + offset);            }            drawChild(canvas, header, getDrawingTime());            canvas.restore();
        我们看到这里有两个判断,第一个是下拉刷新头,第二个是上拉刷新头,其实原理也是一样,将canvas平移到合适的位置,然后调用drawChild方法就可以了。

        这里要简单地说一说topRefreshHeaderView和bottomRefreshHeaderView这两个东西,其实它们是我设计的一个抽象类实现对象,该抽象类如下。

    /**     * 刷新头的抽象类     */    public abstract class HeaderView {        private View headerView;        public static final int STATE_PULLING_UP = 0x30;        public static final int STATE_PULLING_DOWN = 0x31;        public static final int STATE_CAN_RELEASE = 0x32;        public static final int STATE_REFRESHING = 0x33;        public HeaderView(View headerView) {            this.headerView = headerView;        }        /**         * 获得刷新头的View         * @return 实例化是给予的一个自定义View         */        protected View getView() {            return headerView;        }        /**         * 根据状态设置显示内容         * @param state 状态         */        protected abstract void setText(int state);        /**         * 根据状态设置显示图标         * @param state 状态         */        protected abstract void setIcon(int state);    }
        根据这个抽象类的设计,我们可以知道,该抽象类为刷新头的外观提供了一个标准,它应该有一个图标和一个提示的文字内容。当然,PullToRefreshListView有一个默认的刷新头。


        最后就是大家最喜欢的源码了。

import android.animation.Animator;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.support.v4.view.ViewCompat;import android.util.AttributeSet;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.animation.AccelerateDecelerateInterpolator;import android.widget.AbsListView;import android.widget.ListView;import android.widget.TextView;import com.ivan.healthcare.healthcare_android.log.L;/** * 支持下拉刷新的的listView * Created by Ivan on 16/2/14. */public class PullToRefreshListView extends ListView {    private final String TAG = "PullToRefreshListView";    /**     * 默认回滚速度,millis/100dp     */    private final int DEFAULT_BASE_ANIMATING_TIME_PER_100DP = 100;    /**     * 默认刷新背景高度     */    public static final int DEFAULT_WHERE_TO_LOAD = 80;    /**     * 记录上一个手势动作     */    private int lastAction = -1;    /**     * 下拉起始位置     */    private float pullStartY = -1;    /**     * 是否处于“滚动到顶部”状态     */    private boolean isTop = true;    /**     * 是否处于“滚动到底部”状态     */    private boolean isBottom = true;    /**     * 下拉距离     */    private float distanceY = 0;    /**     * 是否处于下拉状态     */    private boolean isPulling = false;    /**     * 回滚动画控制器     */    private ValueAnimator pullCancelAnimator;    private Context context;    /**     * 刷新背景     */    private Drawable refreshDrawable;    /**     * 下拉刷新头     */    private HeaderView topRefreshHeaderView;    /**     * 上拉刷新头     */    private HeaderView bottomRefreshHeaderView;    /**     * 刷新头位置偏移     */    private int offset;    /**     * 刷新回调     */    private OnLoadCallBack onLoadCallBack = new OnLoadCallBack(this) {        @Override        public void onLoad(boolean topOrBottom) {        }        @Override        public void cancelLoad(boolean topOrBottom) {        }    };    public PullToRefreshListView(Context context) {        super(context);        initView(context);    }    public PullToRefreshListView(Context context, AttributeSet attrs) {        super(context, attrs);        initView(context);    }    private void initView(Context context) {        this.context = context;        offset = dp2px(10);        setOnScrollListener(new OnScrollListener() {            @Override            public void onScrollStateChanged(AbsListView view, int scrollState) {            }            @Override            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {                // 没有子view的时候(没有数据,或者被拉到看不到子view),意味着该listView滚动到顶部/底部                if (getChildCount() == 0) {                    isTop = true;                    isBottom = true;                    return;                }                if (firstVisibleItem == 0) {                    View firstView = getChildAt(0);                    if (firstView.getTop() + distanceY >= 0) {                        // 第一个view可见且其相对parent(该listView)的顶部距离大于等于0,意味着该listView也是滚动到顶部                        isTop = true;                        return;                    }                }                isTop = false;                if (firstVisibleItem + visibleItemCount == totalItemCount) {                    View firstView = getChildAt(visibleItemCount - 1);                    if (firstView.getBottom() + distanceY <= getHeight()) {                        // 最后一个view可见且其相对parent(该listView)的底部距离小于等于listView高度,意味着该listView也是滚动到底部                        isBottom = true;                        return;                    }                }                isBottom = false;            }        });    }    /**     * 配置刷新头,当开始下拉/上拉时会执行该方法     * @param topOrBottom true for top, false for bottom     */    private void configureHeader(boolean topOrBottom) {        final TextView header;        if (topOrBottom) {            if (topRefreshHeaderView == null) {                topRefreshHeaderView = onLoadCallBack.getHeaderView(true);                if (topRefreshHeaderView != null) {                    return;                }                header = new TextView(context);                topRefreshHeaderView = new HeaderView(header) {                    @Override                    public void setText(int state) {                        switch (state) {                            case STATE_PULLING_DOWN:                                header.setText("下拉刷新");                                break;                            case STATE_PULLING_UP:                                header.setText("上拉刷新");                                break;                            case STATE_CAN_RELEASE:                                header.setText("释放以刷新");                                break;                            case STATE_REFRESHING:                                header.setText("刷新中...");                                break;                            default:                                break;                        }                    }                    @Override                    public void setIcon(int state) {                    }                };            } else {                return;            }            header.setText("下拉刷新");        } else {            if (bottomRefreshHeaderView == null) {                bottomRefreshHeaderView = onLoadCallBack.getHeaderView(true);                if (bottomRefreshHeaderView != null) {                    return;                }                header = new TextView(context);                bottomRefreshHeaderView = new HeaderView(header) {                    @Override                    public void setText(int state) {                        switch (state) {                            case STATE_PULLING_DOWN:                                header.setText("下拉刷新");                                break;                            case STATE_PULLING_UP:                                header.setText("上拉刷新");                                break;                            case STATE_CAN_RELEASE:                                header.setText("释放以刷新");                                break;                            case STATE_REFRESHING:                                header.setText("刷新中...");                                break;                            default:                                break;                        }                    }                    @Override                    public void setIcon(int state) {                    }                };            } else {                return;            }            header.setText("上拉刷新");        }        header.setTextSize(20);        header.setTextColor(Color.WHITE);        header.setGravity(Gravity.CENTER);        LayoutParams layoutParams = (LayoutParams) header.getLayoutParams();        if (layoutParams == null) {            layoutParams = (LayoutParams) generateDefaultLayoutParams();            header.setLayoutParams(layoutParams);        }        int heightMode = MeasureSpec.getMode(layoutParams.height);        int heightSize = MeasureSpec.getSize(layoutParams.height);        if (heightMode == MeasureSpec.UNSPECIFIED) heightMode = MeasureSpec.EXACTLY;        int maxHeight = getHeight() - getListPaddingTop() - getListPaddingBottom();        if (heightSize > maxHeight) heightSize = maxHeight;        // measure & layout        int ws = MeasureSpec.makeMeasureSpec(getWidth() - getListPaddingLeft() - getListPaddingRight(), MeasureSpec.EXACTLY);        int hs = MeasureSpec.makeMeasureSpec(heightSize, heightMode);        header.measure(ws, hs);        header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        if (lastAction == -1 && ev.getActionMasked() == MotionEvent.ACTION_DOWN) {            // 按下的时候            lastAction = MotionEvent.ACTION_DOWN;            cancelAnimating();            L.d(TAG, "touch down");        } else if (lastAction == MotionEvent.ACTION_MOVE && ev.getActionMasked() == MotionEvent.ACTION_UP) {            // 放开手指,开始回滚            isPulling = false;            lastAction = -1;            startAnimating(distanceY>0);            L.d(TAG, "touch up");        } else if (lastAction == MotionEvent.ACTION_DOWN) {            if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {                // 在按下手指的基础上,开始滑动                if ((isBottom || isTop) && !isPulling) {                    // listView在顶部/底部而且不处于下拉刷新状态,开始下拉/上拉                    pullStartY = ev.getY();                    lastAction = MotionEvent.ACTION_MOVE;                    isPulling = true;                }            }        } else if (lastAction == MotionEvent.ACTION_MOVE) {            if (isTop) {                // 下拉                configureHeader(true);                distanceY = ev.getY() - pullStartY;                L.d(TAG, distanceY + "");                if (distanceY > 0) {                    distanceY = (float) (Math.exp(-ev.getY() / pullStartY / 40) * distanceY);                    // 在下拉状态时取消系统对move动作的响应,完全由本类响应                    ev.setAction(MotionEvent.ACTION_DOWN);                } else {                    distanceY = 0;                    // 在下拉过程中往上拉动该listView使得其回到顶部位置,则将该move动作交由系统进行响应                    ev.setAction(MotionEvent.ACTION_MOVE);                }            }            if (isBottom) {                // 上拉                configureHeader(false);                distanceY = ev.getY() - pullStartY;                L.d(TAG, distanceY + "");                if (distanceY < 0) {                    distanceY = (float) (Math.exp(-pullStartY / ev.getY() / 40) * distanceY);                    // 在上拉状态时取消系统对move动作的响应,完全由本类响应                    ev.setAction(MotionEvent.ACTION_DOWN);                } else {                    distanceY = 0;                    // 在上拉过程中往上拉动该listView使得其回到顶部位置,则将该move动作交由系统进行响应                    ev.setAction(MotionEvent.ACTION_MOVE);                }            }            if (!isTop && !isBottom){                // 在下拉过程中往上拉动listView使listView往下滚动到其没有滚动到顶部,则取消其下拉状态,回到手指按下的初始状态                lastAction = MotionEvent.ACTION_DOWN;                isPulling = false;                distanceY = 0;            }        }        return super.onTouchEvent(ev);    }    @Override    protected void dispatchDraw(Canvas canvas) {        super.dispatchDraw(canvas);        if (distanceY != 0) {            if (refreshDrawable == null) {                refreshDrawable = onLoadCallBack.refreshDrawable();            }            if (refreshDrawable == null) {                canvas.drawColor(Color.GRAY);            } else {                int left = getPaddingLeft();                int top = getPaddingTop();                refreshDrawable.setBounds(left, top, getWidth()+left, getHeight()+top);                refreshDrawable.draw(canvas);            }            // 重画子view            int left = getPaddingLeft();            int top = getPaddingTop();            int bottom = getPaddingBottom();            canvas.save();            if (distanceY > 0) {                canvas.translate(left, top + distanceY);            } else {                canvas.translate(left, -bottom + distanceY);            }            for (int i=0;i 0) {                int whereToLoad = dp2px(onLoadCallBack.whereToLoad(true));                if (distanceY > whereToLoad) {                    topRefreshHeaderView.setText(HeaderView.STATE_CAN_RELEASE);                    topRefreshHeaderView.setIcon(HeaderView.STATE_CAN_RELEASE);                } else if (distanceY < whereToLoad) {                    topRefreshHeaderView.setText(HeaderView.STATE_PULLING_DOWN);                    topRefreshHeaderView.setIcon(HeaderView.STATE_PULLING_DOWN);                }                header = topRefreshHeaderView.getView();                canvas.translate(left, top + distanceY - header.getHeight() - offset);            } else {                int whereToLoad = dp2px(onLoadCallBack.whereToLoad(false));                if (-distanceY > whereToLoad) {                    bottomRefreshHeaderView.setText(HeaderView.STATE_CAN_RELEASE);                    bottomRefreshHeaderView.setIcon(HeaderView.STATE_CAN_RELEASE);                } else if (-distanceY < whereToLoad) {                    bottomRefreshHeaderView.setText(HeaderView.STATE_PULLING_UP);                    bottomRefreshHeaderView.setIcon(HeaderView.STATE_PULLING_UP);                }                header = bottomRefreshHeaderView.getView();                canvas.translate(left, -bottom + distanceY + getHeight() + offset);            }            drawChild(canvas, header, getDrawingTime());            canvas.restore();        }    }    /**     * 下拉结束时进行回滚动画并执行刷新动作     * @param topOrBottom true for top, false for bottom     */    private void startAnimating(final boolean topOrBottom) {        int whereToLoad = dp2px(onLoadCallBack.whereToLoad(topOrBottom));        final boolean toLoad;        if (distanceY > whereToLoad && topOrBottom) {            // 下拉            pullCancelAnimator = ValueAnimator.ofFloat(distanceY, whereToLoad);            toLoad = true;        } else if (-distanceY > whereToLoad && !topOrBottom) {            // 上拉            pullCancelAnimator = ValueAnimator.ofFloat(distanceY, -whereToLoad);            toLoad = true;        } else {            // 回滚            pullCancelAnimator = ValueAnimator.ofFloat(distanceY, 0);            toLoad = false;        }        pullCancelAnimator.setDuration((long) (DEFAULT_BASE_ANIMATING_TIME_PER_100DP*px2dp(Math.abs(distanceY))/100));        pullCancelAnimator.setInterpolator(new AccelerateDecelerateInterpolator());        pullCancelAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                distanceY = (float) animation.getAnimatedValue();                ViewCompat.postInvalidateOnAnimation(PullToRefreshListView.this);            }        });        pullCancelAnimator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animation) {            }            @Override            public void onAnimationEnd(Animator animation) {                post(new Runnable() {                    @Override                    public void run() {                        if (topOrBottom) {                            topRefreshHeaderView.setText(HeaderView.STATE_REFRESHING);                            topRefreshHeaderView.setIcon(HeaderView.STATE_REFRESHING);                        } else {                            bottomRefreshHeaderView.setText(HeaderView.STATE_REFRESHING);                            bottomRefreshHeaderView.setIcon(HeaderView.STATE_REFRESHING);                        }                        pullCancelAnimator = null;                        if (toLoad) {                            onLoadCallBack.onLoad(topOrBottom);                        }                    }                });            }            @Override            public void onAnimationCancel(Animator animation) {                post(new Runnable() {                    @Override                    public void run() {                        pullCancelAnimator = null;                        if (toLoad) {                            onLoadCallBack.cancelLoad(topOrBottom);                        }                    }                });            }            @Override            public void onAnimationRepeat(Animator animation) {            }        });        pullCancelAnimator.start();    }    /**     * 取消回滚动画     */    private void cancelAnimating() {        if (pullCancelAnimator != null) {            pullCancelAnimator.cancel();        }    }    private float px2dp(float pxvalue) {        return (pxvalue - 0.5f) /context.getResources().getDisplayMetrics().density;    }    private int dp2px(float dpvalue) {        return (int) (dpvalue * context.getResources().getDisplayMetrics().density + 0.5f);    }    /**     * 下拉刷新的回调     */    public static abstract class OnLoadCallBack {        private PullToRefreshListView listView;        public OnLoadCallBack(PullToRefreshListView lv) {            this.listView = lv;        }        /**         * 下拉结束后将listView定位到哪个位置等待刷新完成         * @param topOrBottom true for top, false for bottom         * @return listView的定位y坐标值,in dp         */        public int whereToLoad(boolean topOrBottom) {            return DEFAULT_WHERE_TO_LOAD;        }        /**         * 下拉结束后进行刷新的回调         * @param topOrBottom true for top, false for bottom         */        public abstract void onLoad(boolean topOrBottom);        /**         * 取消刷新         * @param topOrBottom true for top, false for bottom         */        public abstract void cancelLoad(boolean topOrBottom);        /**         * 下拉刷新的背景         * @return 背景drawable         */        public Drawable refreshDrawable() {            return new ColorDrawable(Color.GRAY);        }        /**         * 自定义刷新头         * @param topOrBottom true for top, false for bottom         */        public HeaderView getHeaderView(boolean topOrBottom) {            if (topOrBottom) {                listView.destroyTopRefreshHeaderView();            } else {                listView.destroyBottomRefreshHeaderView();            }            return null;        }    }    /**     * 设置下拉刷新回调     * @param cb 回调     */    public void setOnLoadCallBack(OnLoadCallBack cb) {        this.onLoadCallBack = cb;    }    /**     * 刷新动作结束后调用该方法结束刷新,使得listView回滚到顶部     */    public void setLoadingFinish() {        startAnimating(distanceY>0);    }    /**     * 刷新头的抽象类     */    public abstract class HeaderView {        private View headerView;        public static final int STATE_PULLING_UP = 0x30;        public static final int STATE_PULLING_DOWN = 0x31;        public static final int STATE_CAN_RELEASE = 0x32;        public static final int STATE_REFRESHING = 0x33;        public HeaderView(View headerView) {            this.headerView = headerView;        }        /**         * 获得刷新头的View         * @return 实例化是给予的一个自定义View         */        protected View getView() {            return headerView;        }        /**         * 根据状态设置显示内容         * @param state 状态         */        protected abstract void setText(int state);        /**         * 根据状态设置显示图标         * @param state 状态         */        protected abstract void setIcon(int state);    }    protected void destroyTopRefreshHeaderView() {        topRefreshHeaderView = null;    }    protected void destroyBottomRefreshHeaderView() {        bottomRefreshHeaderView = null;    }}


更多相关文章

  1. android:state_pressed是什么意思?
  2. Android实战简易教程-第五十七枪(分享小米手电筒源码)
  3. Android(安卓)自定义View学习(3)--仿IOS风格滑动按钮
  4. Android(安卓)判断网络状态,并且在没有网络的时候,打开网络设置对
  5. android第三天课程 activity生命周期
  6. Activity生命机制与状态保存机制
  7. android倒计时的简单实现
  8. Android弱网测试中关于网络检测的一些借鉴方法
  9. Android(安卓)通过selector改变状态

随机推荐

  1. Linux 下 Sublime Text 3 安装 Godef 进
  2. Linux文件权限概念
  3. linux sar查看网络流量
  4. window与linux查看端口被占用
  5. linux -s和 -f,-e 的区别
  6. 定期清理服务器日志
  7. 获取输出为管道的命令的pid
  8. Linux----------zabbix监控-应用实例
  9. LINUX下搭建简单临时的WWW服务器
  10. 转:——Windows和Linux进程间通信区别