自定义PullToRefreshListView

<h1>优点:可以自定添加头部样式,可以添加上次的时间等等,扩展性非常好<h1>

package com.maogousoft.jsandroidtest;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * Created by zhq_zhao on 2017/8/18.
 */
public class PullToRefreshListView extends ListView {

    private View headerView;
    private float downY;
    private int headerViewHeight;
    /**
     * 状态:下拉刷新
     */
    private static final int STATE_PULL_TO_REFRESH = 0;
    /**
     * 状态:松开刷新
     */
    private static final int STATE_RELEASE_REFRESH = 1;
    /**
     * 状态:正在刷新
     */
    private static final int STATE_REFRESHING = 2;
    /**
     * 当前状态
     */
    private int currentState = STATE_PULL_TO_REFRESH;  // 默认是下拉刷新状态
    private ImageView iv_arrow;
    private ProgressBar progress_bar;
    private TextView tv_state;
    private int topDistance = 100;//设置下拉的时候距离顶部的距离
    private RotateAnimation upAnim;
    private RotateAnimation downAnim;
    private OnRefreshingListener mOnRefreshingListener;
    private View footerView;
    private int footerViewHeight;
    /**
     * 正在加载更多
     */
    private boolean loadingMore;
    /**
     * 正在刷新
     */
    private boolean loadingRefrush=false;


    /**设置具体顶部最大距离
     *
     * @param topDistance
     */
    public void setTopDistance(int topDistance) {
    this.topDistance=topDistance;
    }


    public PullToRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeaderView();
        initFooterView();
    }



    private void initHeaderView() {
        headerView = View.inflate(getContext(), R.layout.header_view, null);
        iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
        progress_bar = (ProgressBar) headerView.findViewById(R.id.progress_bar);
        showRefreshingProgressBar(false);
        tv_state = (TextView) headerView.findViewById(R.id.tv_state);
        headerView.measure(0, 0);  // 主动触发测量,mesure内部会调用onMeasure
        headerViewHeight = headerView.getMeasuredHeight();
        hideHeaderView();
        super.addHeaderView(headerView);//告诉父控件去添加头部信息
        upAnim = createRotateAnim(0f, -180f);
        downAnim = createRotateAnim(-180f, -360f);
    }

    private void initFooterView() {
        footerView = View.inflate(getContext(), R.layout.footer_view, null);
        footerView.measure(0, 0);// 主动触发测量,mesure内部会调用onMeasure
        footerViewHeight = footerView.getMeasuredHeight();
        hideFooterView();
        super.addFooterView(footerView);//告诉父控件去添加尾部信息

        super.setOnScrollListener(new OnScrollListener() {

            // 当ListView滚动的状态发生改变的时候会调用这个方法
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == OnScrollListener.SCROLL_STATE_IDLE  // ListView处于空闲状态
                        && getLastVisiblePosition() == getCount() - 1  // 界面上可见的最后一条item是ListView中最后的一条item
                        && loadingMore == false  // 如果当前没有去做正在加载更多的事情
                        &&loadingRefrush==false  ) {            //没有正在刷新

                    loadingMore = true;
                    showFooterView();
                    setSelection(getCount() - 1);

                    if (mOnRefreshingListener != null) {
                        mOnRefreshingListener.onLoadMore();
                    }
                }
            }

            // 当ListView滚动的时候会调用这个方法
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                // Toast.makeText(getContext(),view+":"+firstVisibleItem+":"+visibleItemCount+":"+totalItemCount,Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void hideFooterView() {
        int paddingTop = -footerViewHeight;
        setFooterViewPaddingTop(paddingTop);
    }

    private void showFooterView() {
        int paddingTop = 0;
        setFooterViewPaddingTop(paddingTop);
    }

    private void setFooterViewPaddingTop(int paddingTop) {
        footerView.setPadding(0, paddingTop, 0, 0);
    }

    /**
     * 设置显示进度的圈圈
     *
     * @param showProgressBar 如果是true,则显示ProgressBar,否则的话显示箭头
     */
    private void showRefreshingProgressBar(boolean showProgressBar) {
        progress_bar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
        iv_arrow.setVisibility(!showProgressBar ? View.VISIBLE : View.GONE);

        if (showProgressBar) {
            iv_arrow.clearAnimation(); // 有动画的View要清除动画才能真正的隐藏
        }
    }

    /**
     * 创建旋转动画
     *
     * @param fromDegrees 从哪个角度开始转
     * @param toDegrees   转到哪个角度
     * @return
     */
    private RotateAnimation createRotateAnim(float fromDegrees, float toDegrees) {
        int pivotXType = RotateAnimation.RELATIVE_TO_SELF;    // 旋转点的参照物
        int pivotYType = RotateAnimation.RELATIVE_TO_SELF;    // 旋转点的参照物
        float pivotXValue = 0.5f;  // 旋转点x方向的位置
        float pivotYValue = 0.5f;  // 旋转点y方向的位置
        RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue);
        ra.setDuration(300);
        ra.setFillAfter(true); // 让动画停留在结束位置
        return ra;
    }

    /**
     * 隐藏HeaderView
     */
    private void hideHeaderView() {
        int paddingTop = -headerViewHeight;
        setHeaderViewPaddingTop(paddingTop);
    }

    /**
     * 显示HeaderView
     */
    private void showHeaderView() {
        int paddingTop = 0;
        setHeaderViewPaddingTop(paddingTop);
    }

    /**
     * 设置HeaderView的paddingTop
     *
     * @param paddingTop
     */
    private void setHeaderViewPaddingTop(int paddingTop) {
        headerView.setPadding(0, paddingTop, 0, 0);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (currentState == STATE_REFRESHING) {
                    // 如果当前已经是“正在刷新“的状态了,则不用去处理下拉刷新了
                    loadingRefrush=true;
                    return super.onTouchEvent(ev);
                }

                int fingerMoveDistanceY = (int) (ev.getY() - downY);      // 手指移动的距离
                // 如果是向下滑动,并且界面上可见的第一条item是ListView的索引为0的item时我们才处理下拉刷新的操作
                if (fingerMoveDistanceY > 0 && getFirstVisiblePosition() == 0) {
                    if (fingerMoveDistanceY > 20) {
                        int paddingTop = -headerViewHeight + fingerMoveDistanceY;
                        if (paddingTop < topDistance) {//不让下拉过长
                            setHeaderViewPaddingTop(paddingTop);
                        }

                        if (paddingTop < 0 && currentState != STATE_PULL_TO_REFRESH) {
                            // 如果paddingTop小于0,说明HeaderView没有完全显示出来,则进入下拉刷新的状态
                            currentState = STATE_PULL_TO_REFRESH;
                            tv_state.setText("下拉刷新");
                            iv_arrow.startAnimation(downAnim);
                            showRefreshingProgressBar(false);
                            // 让箭头转一下
                        } else if (paddingTop >= 0 && currentState != STATE_RELEASE_REFRESH) {
                            // 如果paddingTop>=0,说明HeaderView已经完全显示出来,则进入松开刷新的状态
                            currentState = STATE_RELEASE_REFRESH;
                            tv_state.setText("松开刷新");
                            iv_arrow.startAnimation(upAnim);
                            showRefreshingProgressBar(false);

                        }
                        return true;
                    }

                }else if(fingerMoveDistanceY < 0&&getLastVisiblePosition()==getCount()){//这样是为了防止正在刷新的时候上拉加载出来
                    loadingRefrush=false;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (currentState == STATE_RELEASE_REFRESH) {
                    // 如果当前状态是松开刷新,并且抬起了手,则进入正在刷新状态
                    currentState = STATE_REFRESHING;
                    tv_state.setText("正在刷新");
                    showRefreshingProgressBar(true);
                    showHeaderView();

                    if (mOnRefreshingListener != null) {
                        mOnRefreshingListener.onRefreshing();
                    }
                } else if (currentState == STATE_PULL_TO_REFRESH) {
                    // 如果抬起手时是下拉刷新状态,则把HeaderView完成隐藏
                    hideHeaderView();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    public void setOnRefreshingListener(OnRefreshingListener mOnRefreshingListener) {
        this.mOnRefreshingListener = mOnRefreshingListener;
    }

    /**
     * ListView刷新的监听器
     */
    public interface OnRefreshingListener {
        /**
         * 当ListView可以刷新数据的时候会调用这个方法
         */
        void onRefreshing();

        /**
         * 当ListView可以加载更多 的时候会调用这个方法
         */
        void onLoadMore();
    }

    /**
     * 联网刷新数据的操作已经完成了
     */
    public void onRefreshComplete() {
        hideHeaderView();
        currentState = STATE_PULL_TO_REFRESH;
        showRefreshingProgressBar(false);
    }

    /**
     * 加载更多新数据的操作已经完成了
     */
    public void onLoadmoreComplete() {
        hideFooterView();
        loadingMore = false;
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BACKWASH2038

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值