android 上拉加载下拉刷新——MyRefreshListView

1.自定义MyRefreshListView继承ListView
public class MyRefreshListView extends ListView implements OnScrollListener {
    private Context context;
    private LayoutInflater mInflater;

    /**
     * 判罚是否可以下拉刷新
     */
    private boolean canRefresh = false;

    /**
     * 判罚是否可以上拉加载
     */
    private boolean canLoadMore = false;

    /**
     * 屏幕上第一个item的索引
     */
    private int mFirstItemIndex;

    /**
     * 屏幕上最后一个item索引
     */
    private int mLastItemIndex;

    /**
     * 该listView的总数
     */
    private int mItemCount;

    //================================================== headerView   start ============================================

    private LinearLayout mHeaderView;
    private int headerViewId = -1;
    private int headerArrowImgId;
    private int headerProgressPbId;
    private int headerTipTvId;
    private int headerTimeTvId;
    private ProgressBar headerProgressBar;
    private ImageView headerArrowImg;
    private TextView headerTimeTv;
    private TextView headerTipTv;
    private int mHeaderViewHeight;
    private int mHeaderViewWidth;


    /**
     * 在第一次显示时,是否需要刷新;<\br>
     * if true  会加载一次onRefreshing方法,触发刷新监听
     */
    private boolean headerNeedRefreshAtFirstShown = false;

    /**
     * 在第一次显示时,是否需要刷新;
     * if true  会加载一次onRefreshing方法,触发刷新监听
     *
     * @param headerNeedRefreshAtFirstShown
     */
    public void setHeaderNeedRefreshAtFirstShown(boolean headerNeedRefreshAtFirstShown) {
        this.headerNeedRefreshAtFirstShown = headerNeedRefreshAtFirstShown;
    }

    // 下拉刷新的状态标识 start

    /**
     * 松开刷新
     */
    private final static int HEADER_RELEASE_TO_REFRESH = 0;

    /**
     * 下拉刷新
     */
    private final static int HEADER_PULL_TO_REFRESH = 1;

    /**
     * 正在刷新
     */
    private final static int HEADER_REFRESHING = 2;

    /**
     * 刷新完成 or 什么都没做,恢复原状态。
     */
    private final static int HEADER_REFRESHED_FINISH = 3;

    // 下拉刷新的状态标识 end

    /**
     * 往下拉时的提示语
     */
    private String headerPullToRefreshTip = "下拉刷新";

    /**
     * 释放刷新提示语
     */
    private String headerReleaseToRefreshTip = "松手刷新";

    /**
     * 正在刷新提示语
     */
    private String headerRefreshingTip = "正在刷新...";

    /**
     * 设置往下拉时的提示语
     *
     * @param string
     */
    public void setHeaderPullToRefreshString(String string) {
        this.headerPullToRefreshTip = string;
    }

    /**
     * 设置释放刷新的提示语
     *
     * @param string
     */
    public void setHeaderReleaseToRefreshString(String string) {
        this.headerReleaseToRefreshTip = string;
    }

    /**
     * 设置释放刷新的提示语
     *
     * @param string
     */
    public void setHeaderRefreshingString(String string) {
        this.headerRefreshingTip = string;
    }

    /**
     * 下拉刷新HeadView的实时状态
     */
    private int mHeadState;

    //箭头动画 start

    /**
     * 箭头旋转动画
     */
    private RotateAnimation headerArrowAnimation;

    /**
     * 箭头还原动画
     */
    private RotateAnimation headerArrowReverseAnimation;

    /**
     * 箭头旋转延时
     */
    private int headerAarrowDuration = 250;

    /**
     * 设置箭头旋转延时
     *
     * @param arrowDuration
     */
    public void setHeaderArrowDuration(int arrowDuration) {
        this.headerAarrowDuration = arrowDuration;
        headerArrowAnimation.setDuration(arrowDuration);
        headerArrowReverseAnimation.setDuration(arrowDuration);
    }

    /**
     * 箭头旋转加速器
     */
    private Interpolator headerArrowInterpolator = new LinearInterpolator();

    /**
     * 设置箭头旋转加速器
     */
    public void setHeaderArrowInterpolator(Interpolator arrowInterpolator) {
        this.headerArrowInterpolator = arrowInterpolator;
        headerArrowAnimation.setInterpolator(arrowInterpolator);
        headerArrowReverseAnimation.setInterpolator(arrowInterpolator);
    }

    //箭头动画  end

    //时间 start

    /**
     * 时间提示语
     */
    private String headerTimeTip = "最近更新时间";

    /**
     * 设置时间提示语
     *
     * @param timeTipString
     */
    public void setHeaderTimeTipString(String timeTipString) {
        this.headerTimeTip = timeTipString;
    }

    /**
     * 时间显示格式
     */
    private String headerTimeDateFormat = "yyyy年MM月dd日 HH:mm";


    /**
     * 设置时间显示格式
     *
     * @param timeDateFormat 举例:"yyyy年MM月dd日 HH:mm"
     */
    public void setHeaderTimeDateFormat(String timeDateFormat) {
        this.headerTimeDateFormat = timeDateFormat;
    }

    //时间 end

    /**
     * 下拉刷新完成后,头部移动动画距离
     */
    private float headerFinishTranslteDistance;

    /**
     * 下拉刷新完成后的提示语
     */
    private String headerRefreshedFinishTip = "下拉刷新成功";

    /**
     * 设置下拉刷新完成后的提示语
     *
     * @param headerRefreshedFinishTip
     */
    public void setHeaderRefreshedFinishTipString(String headerRefreshedFinishTip) {
        this.headerRefreshedFinishTip = headerRefreshedFinishTip;
    }

    /**
     * 下拉完成后的移动动画
     */
    private TranslateAnimation translateAnimation;

    /**
     * 头部隐藏动画延迟时间
     */
    private int headerGoBackLocationDelayTime = 200;


    /**
     * 设置头部隐藏动画延迟时间
     *
     * @param headerGoBackLocationDelayTime
     */
    public void setHeaderGoBackLocationDelayTime(int headerGoBackLocationDelayTime) {
        this.headerGoBackLocationDelayTime = headerGoBackLocationDelayTime;
    }

    //================================================== headerView   end ==============================================

    //================================================== footerView   start ============================================

    private int footerViewId;
    private int footerProgressId;
    private int footerTipTvId;
    private LinearLayout mFooterView;
    private ProgressBar footerProgressBar;
    private TextView footerTipTv;

    /**
     * 使用自动加载更多
     */
    private boolean footerUseAutoLoadMore = false;

    /**
     * 设置是否自动加载更多
     *
     * @param
     */
    public void setFooterAutoLoadMore(boolean useAutoLoadMore) {
        this.footerUseAutoLoadMore = useAutoLoadMore;
    }

    /**
     * 正在加载更多提示语
     */
    private String footerLoadMoreTip = "正在加载...";

    /**
     * 设置正在加载更多提示语
     */
    public void setFooterLoadMoreString(String loadMoreTip) {
        this.footerLoadMoreTip = loadMoreTip;
    }

    /**
     * 加载完成提示语
     */
    private String footerLoadMoreFinishTip = "点击加载完成";

    /**
     * 设置加载完成提示语
     */
    public void setFooterLoadMoreFinishString(String loadMoreFinishTip) {
        this.footerLoadMoreFinishTip = loadMoreFinishTip;
    }

    /**
     * 自动加载更多完成提示语
     */
    private String footerAutoLoadMoreFinishTip = "上拉加载更多";

    /**
     * 设置自动加载更多完成提示语
     */
    public void setFooterAutoLoadMoreFinishString(String autoLoadMoreFinishTip) {
        this.footerAutoLoadMoreFinishTip = autoLoadMoreFinishTip;
    }

    /**
     * 判断是否可以加载更多
     */
    private boolean footerNoMoreCanLoad = false;

    /**
     * 已无加载更多提示语
     */
    private String footerNoMoreCanLoadTip = "已无更多可加载";

    /**
     * 已无更多提示语显示的持续时间
     */
    private long footerNoMoreTipDelayTime = 3000;

    /**
     * 设置已无更多提示语显示的持续时间
     */
    public void setFooterNoMoreTipDelayTime(long noMoreTipDelayTime) {
        this.footerNoMoreTipDelayTime = noMoreTipDelayTime;
    }

    /**
     * 设置已无更多提示语
     *
     * @param noMoreCanLoadString
     */
    public void setFooterNoMoreCanLoadString(String noMoreCanLoadString) {
        this.footerNoMoreCanLoadTip = noMoreCanLoadString;
    }

    /**
     * footer状态
     */
    private int mFooterState;

    // 加载更多的状态标识 start

    /**
     * 加载中
     */
    public final static int FOOTER_LOADING = 1;

    /**
     * 完成刷新
     */
    private final static int FOOTER_LOAD_MORE_FINISH = 2;

    /****** 无更多 *****/
    private final static int FOOTER_NO_MORE_DATA = 3;

    // 加载更多的状态标识 end

    //================================================== footerView    end =============================================

    //==================================================  触摸监听  start  ================================================

    /**
     * 开始触摸的y坐标
     */
    private float mStartY;

    /**
     * 下拉距离比例,到达此比列显示释放刷新界面,跟进查看用法。
     */
    private int RATIO = 3;

    /**
     * 判断上个布局是不是释放刷新
     */
    private boolean HEADER_LAST_VIEW_IS_RELEASE;

    //==================================================  触摸监听  end  ==================================================

    //==================================================   接口 start  ==================================================

    /**
     * 下拉刷新监听
     */
    private MyRefreshListener myRefreshListener = null;

    /**
     * 下拉刷新接口
     *
     * @author yangshuai
     */
    public interface MyRefreshListener {
        public void OnRefreshListener();
    }

    /**
     * 下拉刷新接口监听
     *
     * @param myRefreshListener
     */
    public void setRefreshListener(MyRefreshListener myRefreshListener) {
        if (myRefreshListener != null) {
            canRefresh = true;
            this.myRefreshListener = myRefreshListener;
        }
    }

    /**
     * 上拉加载接口监听
     */
    private MyLoadMoreListener myLoadMoreListener = null;

    /**
     * 上拉加载接口
     *
     * @author yangshuai
     */
    public interface MyLoadMoreListener {
        public void OnLoadMore();
    }

    /**
     * 设置上拉加载监听
     *
     * @param myLoadMoreListener
     */
    public void setLoadMoreListener(MyLoadMoreListener myLoadMoreListener) {
        canLoadMore = true;
        if (myLoadMoreListener != null) {
            this.myLoadMoreListener = myLoadMoreListener;
        }
    }

    //==================================================   接口 end  ====================================================

    //==================================================   初始化方法 start  ==============================================

    public MyRefreshListView(Context context, AttributeSet attrs,
                             int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public MyRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyRefreshListView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        this.context = context;
        setCacheColorHint(context.getResources().getColor(android.R.color.transparent));
        setOnLongClickListener(null);
        setOnScrollListener(this);
        mInflater = LayoutInflater.from(context);
    }

    //==================================================   初始化方法 end  ================================================

    //========================================================= headerView相关方法  start==================================

    /**
     * 设置头部资源文件
     *
     * @param headerViewId 头部布局需要有如下几个控件:
     *                     箭头ImageView,进度条ProgressBar,信息提示TextView,更新时间TextView
     */
    public void setHeaderResourse(int headerViewId, int arrowImgId, int progressPbId, int tipTvId, int timeTvId) {
        this.headerViewId = headerViewId;
        this.headerArrowImgId = arrowImgId;
        this.headerProgressPbId = progressPbId;
        this.headerTipTvId = tipTvId;
        this.headerTimeTvId = timeTvId;
        setHeaderView();
    }

    /**
     * 设置头部布局
     */
    private void setHeaderView() {
        mHeaderView = (LinearLayout) mInflater.inflate(headerViewId, null);
        headerProgressBar = (ProgressBar) mHeaderView.findViewById(headerProgressPbId);
        headerArrowImg = (ImageView) mHeaderView.findViewById(headerArrowImgId);
        headerArrowImg.setMinimumHeight(70);
        headerArrowImg.setMinimumWidth(50);
        headerTimeTv = (TextView) mHeaderView.findViewById(headerTimeTvId);
        headerTipTv = (TextView) mHeaderView.findViewById(headerTipTvId);
        measureView(mHeaderView);
        mHeaderViewHeight = mHeaderView.getMeasuredHeight();
        mHeaderViewWidth = mHeaderView.getMeasuredWidth();
        headerFinishTranslteDistance = -mHeaderViewHeight;
        mHeaderView.setPadding(0, -1 * mHeaderViewHeight, 0, 0);
        mHeaderView.invalidate();

        addHeaderView(mHeaderView, null, false);
        if (headerNeedRefreshAtFirstShown) {
            mHeadState = HEADER_REFRESHING;
            onRefreshing();
        } else {
            mHeadState = HEADER_REFRESHED_FINISH;
        }
        showHeaderViewByState();
        initArrowRotateAnim();
    }

    /**
     * 测量HeadView宽高(注意:此方法仅适用于LinearLayout)
     *
     * @param view
     */
    private void measureView(View view) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params == null) {
            params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childeWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
        int PHeight = params.height;
        int childeHeightSpec;
        if (PHeight > 0) {
            childeHeightSpec = MeasureSpec.makeMeasureSpec(PHeight, MeasureSpec.EXACTLY);
        } else {
            childeHeightSpec = MeasureSpec.makeMeasureSpec(PHeight, MeasureSpec.UNSPECIFIED);
        }
        view.measure(childeWidthSpec, childeHeightSpec);
    }

    /**
     * 初始化箭头旋转动画
     */
    private void initArrowRotateAnim() {
        headerArrowAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        headerArrowAnimation.setDuration(headerAarrowDuration);
        headerArrowAnimation.setInterpolator(headerArrowInterpolator);
        headerArrowAnimation.setFillAfter(true);
        headerArrowReverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        headerArrowReverseAnimation.setDuration(headerAarrowDuration);
        headerArrowReverseAnimation.setInterpolator(headerArrowInterpolator);
        headerArrowReverseAnimation.setFillAfter(true);
    }

    /**
     * 通过不同的状态改变头部的显示
     */
    private void showHeaderViewByState() {
        switch (mHeadState) {
            case HEADER_RELEASE_TO_REFRESH:
                clearAnimation();
                headerProgressBar.setVisibility(View.GONE);
                headerArrowImg.setVisibility(View.VISIBLE);
                headerArrowImg.clearAnimation();
                headerArrowImg.startAnimation(headerArrowAnimation);
                headerTipTv.setText(headerReleaseToRefreshTip);
                break;
            case HEADER_PULL_TO_REFRESH:
                clearAnimation();
                headerProgressBar.setVisibility(View.GONE);
                headerArrowImg.setVisibility(View.VISIBLE);
                headerArrowImg.clearAnimation();
                setHeaderTipTvText(headerPullToRefreshTip);
                if (HEADER_LAST_VIEW_IS_RELEASE) {
                    HEADER_LAST_VIEW_IS_RELEASE = false;
                    headerArrowImg.startAnimation(headerArrowReverseAnimation);
                }
                break;
            case HEADER_REFRESHING:
                clearAnimation();
                mHeaderView.setPadding(0, 0, 0, 0);
                headerArrowImg.clearAnimation();
                headerArrowImg.setVisibility(View.GONE);
                headerProgressBar.setVisibility(View.VISIBLE);
                headerTipTv.setText(headerRefreshingTip);
                break;
            case HEADER_REFRESHED_FINISH:
                translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.ABSOLUTE, headerFinishTranslteDistance);
                translateAnimation.setDuration(headerGoBackLocationDelayTime);
                translateAnimation.setFillAfter(true);
                translateAnimation.setInterpolator(new LinearInterpolator());
                translateAnimation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        headerProgressBar.setVisibility(View.GONE);
                        headerArrowImg.setVisibility(View.VISIBLE);
                        headerArrowImg.clearAnimation();
                        headerArrowImg.startAnimation(headerArrowAnimation);
                        setHeaderTipTvText(headerRefreshedFinishTip);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        clearAnimation();
                        mHeaderView.setPadding(0, -1 * mHeaderViewHeight, 0, 0);
                        headerArrowImg.clearAnimation();
                        setHeaderTipTvText(headerPullToRefreshTip);
                    }
                });
                startAnimation(translateAnimation);
                break;

            default:
                break;
        }
    }

    /**
     * 设置提示TextView文字
     */
    private void setHeaderTipTvText(String string) {
        headerTipTv.setText(string);
    }

    /**
     * 正在下拉刷新中
     */
    private void onRefreshing() {
        if (myRefreshListener != null) {
            myRefreshListener.OnRefreshListener();
        }
    }

    /**
     * 下拉刷新完成
     */
    public void onRefreshComplete() {

        //在已经无更多加载的情况下,如果下拉刷新的话加载更多可以再启动
        footerNoMoreCanLoad = false;
        mHeadState = HEADER_REFRESHED_FINISH;
        headerTimeTv.setText(getNewDate());
        showHeaderViewByState();
    }

    /**
     * 下拉刷新逻辑处理
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!canRefresh || mFirstItemIndex != 0 || mFooterState == FOOTER_LOADING) {
            return super.onTouchEvent(ev);
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mStartY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float tempY = ev.getY();
                if (mHeadState == HEADER_REFRESHING) {
                    break;
                }
                if (mHeadState == HEADER_REFRESHED_FINISH) {
                    if (tempY - mStartY > 0) {
                        mHeadState = HEADER_PULL_TO_REFRESH;
                        showHeaderViewByState();
                    }
                }
                if (mHeadState == HEADER_PULL_TO_REFRESH) {
                    setSelection(0);
                    if ((tempY - mStartY) / RATIO >= mHeaderViewHeight) {
                        mHeadState = HEADER_RELEASE_TO_REFRESH;
                        HEADER_LAST_VIEW_IS_RELEASE = true;
                        showHeaderViewByState();
                    } else if (tempY - mStartY <= 0) {
                        mHeadState = HEADER_REFRESHED_FINISH;
                        showHeaderViewByState();
                    }
                    if (mHeadState == HEADER_PULL_TO_REFRESH) {
                        float paddingTop = -1 * mHeaderViewHeight + (tempY - mStartY) / RATIO;
                        mHeaderView.setPadding(0, (int) paddingTop, 0, 0);
                        headerFinishTranslteDistance = -mHeaderViewHeight - paddingTop;
                    }
                }
                if (mHeadState == HEADER_RELEASE_TO_REFRESH) {
                    setSelection(0);
                    if (tempY - mStartY > 0 && (tempY - mStartY) / RATIO < mHeaderViewHeight) {
                        mHeadState = HEADER_PULL_TO_REFRESH;
                        showHeaderViewByState();
                    } else if (tempY - mStartY <= 0) {
                        mHeadState = HEADER_REFRESHED_FINISH;
                        showHeaderViewByState();
                    }
                    if (mHeadState == HEADER_RELEASE_TO_REFRESH) {
                        mHeaderView.setPadding(0, (int) (tempY - mStartY) / RATIO - mHeaderViewHeight, 0, 0);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mHeadState == HEADER_REFRESHING) {
                    break;
                }
                if (mHeadState == HEADER_PULL_TO_REFRESH) {
                    mHeadState = HEADER_REFRESHED_FINISH;
                    showHeaderViewByState();
                }
                if (mHeadState == HEADER_RELEASE_TO_REFRESH) {
                    headerFinishTranslteDistance = -mHeaderViewHeight;
                    mHeadState = HEADER_REFRESHING;
                    showHeaderViewByState();
                    onRefreshing();
                }
                break;

            default:
                break;
        }
        return super.onTouchEvent(ev);
    }
    //========================================================= headerView相关方法  end====================================

    //========================================================= footerView相关方法  start==================================

    /**
     * 设置Footer资源id,需要布局文件中有progressbar和TextView两个控件
     *
     * @param mFooterView
     * @param mFooterProgress progressBar
     * @param mFooterTipTv    TextView
     */
    public void setFooterResourse(int mFooterView, int mFooterProgress, int mFooterTipTv) {
        this.footerViewId = mFooterView;
        this.footerProgressId = mFooterProgress;
        this.footerTipTvId = mFooterTipTv;
        setFooterView();
    }

    /**
     * 设置footer布局
     */
    private void setFooterView() {
        mFooterView = (LinearLayout) mInflater.inflate(footerViewId, null);
        footerProgressBar = (ProgressBar) mFooterView.findViewById(footerProgressId);
        footerTipTv = (TextView) mFooterView.findViewById(footerTipTvId);
        addFooterView(mFooterView);
        mFooterView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (!canLoadMore || canRefresh && mHeadState == HEADER_REFRESHING) {
                    return;
                }
                if (footerNoMoreCanLoad) {
                    return;
                }
                mFooterState = FOOTER_LOADING;
                showFooterViewByState();
                onLoadMore();
            }
        });
        mFooterState = FOOTER_LOAD_MORE_FINISH;
    }

    /**
     * 通过mFooterState改变footer布局显示
     */
    private void showFooterViewByState() {
        switch (mFooterState) {
            case FOOTER_LOADING:
                hideFooterViewHandler.removeMessages(0);
                mFooterView.setVisibility(View.VISIBLE);
                footerProgressBar.setVisibility(View.VISIBLE);
                footerTipTv.setText(footerLoadMoreTip);
                break;
            case FOOTER_LOAD_MORE_FINISH:
                mFooterView.setVisibility(View.VISIBLE);
                footerProgressBar.setVisibility(View.GONE);
                footerTipTv.setText(footerUseAutoLoadMore ? footerAutoLoadMoreFinishTip : footerLoadMoreFinishTip);
                hideFooterViewHandler.removeMessages(0);
                hideFooterViewHandler.sendEmptyMessageDelayed(0, footerNoMoreTipDelayTime);
                break;
            case FOOTER_NO_MORE_DATA:
                mFooterView.setVisibility(View.VISIBLE);
                footerProgressBar.setVisibility(View.GONE);
                footerTipTv.setText(footerNoMoreCanLoadTip);
                hideFooterViewHandler.removeMessages(0);
                hideFooterViewHandler.sendEmptyMessageDelayed(0, footerNoMoreTipDelayTime);
                break;
            default:
                break;
        }
    }

    /**
     * 执行上拉加载数据更新
     */
    private void onLoadMore() {
        if (myLoadMoreListener != null) {
            myLoadMoreListener.OnLoadMore();
        }
    }

    /**
     * 设置加载完成
     */
    public void onLoadMoreComplete() {
        mFooterState = FOOTER_LOAD_MORE_FINISH;
        showFooterViewByState();
    }

    /**
     * 延时隐藏footerView
     */
    private Handler hideFooterViewHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            mFooterView.setVisibility(View.GONE);
            super.handleMessage(msg);

        }
    };

    /**
     * 已无更多加载
     */
    public void setFooterNoMoreDataWillBeLoadFlag() {
        footerNoMoreCanLoad = true;
        mFooterState = FOOTER_NO_MORE_DATA;
        showFooterViewByState();
    }

    /**
     * 加载更多逻辑处理
     *
     * @param view
     * @param scrollState
     */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (footerNoMoreCanLoad || mFooterState == FOOTER_LOADING) {
            return;
        }
        if (canLoadMore) {
            if (!(mLastItemIndex == mItemCount && scrollState == SCROLL_STATE_IDLE) || mFooterState == FOOTER_LOADING) {
                return;
            }
            if (canRefresh && mHeadState == HEADER_REFRESHING) {
                mFooterView.setVisibility(View.GONE);
            } else if (footerUseAutoLoadMore) {
                mFooterState = FOOTER_LOADING;
                onLoadMore();
                showFooterViewByState();
            } else {
                mFooterState = FOOTER_LOAD_MORE_FINISH;
                showFooterViewByState();
            }
        } else {
            mFooterView.setVisibility(View.GONE);
            this.removeFooterView(mFooterView);
        }
    }

    /**
     * 获取屏幕上第一个和最后一个item的索引
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
        mFirstItemIndex = firstVisibleItem;
        mLastItemIndex = firstVisibleItem + visibleItemCount - 2;
        mItemCount = totalItemCount - 2;
    }

    //========================================================= footerView相关方法  end====================================


    /**
     * 设置适配器,加载最开始的刷新时间
     *
     * @param adapter
     */
    public void setAdapter(BaseAdapter adapter) {
        headerTimeTv.setText(getNewDate());
        super.setAdapter(adapter);
    }

    /**
     * 获取最新时间
     *
     * @return
     */
    private String getNewDate() {
        return headerTimeTip + new SimpleDateFormat(headerTimeDateFormat, Locale.CHINA).format(new Date());
    }

}

使用方法

首先要自定义头部和尾部的布局

头部布局要求:线性布局 
头部布局需要有如下几个控件: 箭头ImageView默认向下指向,进度条ProgressBar,信息提示TextView,更新时间TextView。 
尾部布局要求:线性布局 
需要布局文件中有progressbar和TextView两个控件。

头部示例(这个示例是SingleLayoutListView作者的)
<?xml version="1.0" encoding="utf-8"?>
<!-- ListView的头部 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:orientation="horizontal" >

    <!-- 内容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="8dp"
        android:paddingTop="8dp" >

        <!-- 箭头图像、进度条 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="30dp" >

            <!-- 箭头 -->

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:contentDescription="@string/app_name"
                android:src="@drawable/icon_arrow" />

            <!-- 进度条 -->

            <ProgressBar
                android:id="@+id/head_progressBar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:indeterminateDrawable="@drawable/image_progress"
                android:visibility="gone" />
        </FrameLayout>

        <!-- 提示、最近更新 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <!-- 提示 -->

            <TextView
                android:id="@+id/head_tipsTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="释放提示"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <!-- 最近更新 -->

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="6dp"
                android:text="更新时间"
                android:textColor="@android:color/black"
                android:textSize="12sp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>
尾部布局示例(这个示例是SingleLayoutListView作者的)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal"
    android:padding="15dp" >

    <ProgressBar
        android:id="@+id/pull_to_refresh_progress"
        style="@android:style/Widget.ProgressBar.Small.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:visibility="gone" >
    </ProgressBar>

    <TextView
        android:id="@+id/load_more"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10.0dp"
        android:gravity="center"
        android:text="加载更多"
        android:textColor="@android:color/black" >
    </TextView>

</LinearLayout>
加载适配器之前要先把头布局和尾布局传入控件
myRefreshListView.setHeaderResourse(R.layout.pull_to_refresh_head, R.id.head_arrowImageView, R.id.head_progressBar, R.id.                                    head_tipsTextView, R.id.head_lastUpdatedTextView);
myRefreshListView.setFooterResourse(R.layout.pull_to_refresh_load_more, R.id.pull_to_refresh_progress, R.id.load_more);
监听方法
myRefreshListView.setRefreshListener(new MyRefreshListener() {

            @Override
            public void OnRefreshListener() {
            //下拉刷新监听
            }
        });
myRefreshListView.setLoadMoreListener(new MyLoadMoreListener() {

            @Override
            public void OnLoadMore() {
            //加载更多监听
            }
        });
在数据加载完成后调用如下方法,更换布局显示:
//下拉刷新完成
myRefreshListView.onRefreshComplete();

//上拉加载完成
myRefreshListView.onLoadMoreComplete();

//上拉加载数据已无更多
myRefreshListView.setFooterNoMoreDataWillBeLoadFlag();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值