自定义下拉刷新的listview

自定义下拉刷新的listview

listview的下拉刷新功能的实现依靠在listview前面加上头布局,通过判断头布局的位置确实用户是否下拉,然后根据情况进行处理

1. 自定义一个类继承ListView

2. 自定义一个布局用于加入listView的头布局中

自定义的类代码如下:

public class ReflashListView extends ListView implements OnScrollListener {

    private final static int PULL_To_REFRESH = 0; // 下拉的状态值
    private final static int REFRESHING = 1;// 正在刷新的状态值
    private final static int RELEASE_REFRESH = 2; // 松开刷新的状态值

    private LayoutInflater mInflater;
    private View mheardView;
    private ImageView ivArrow;
    private TextView tvTitle;
    private TextView tvTime;
    private ProgressBar pbProgress;
    private int mhearderHeight; // 下拉刷新布局的高度
    private boolean isreflash; // 是否可以下拉刷新
    private int startY = -1;
    private int state = PULL_To_REFRESH; // 记录当前状态

    private Animation animUp;
    private Animation animDown;

    public ReflashListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initViews();
    }

    public ReflashListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews();
    }

    public ReflashListView(Context context) {
        super(context);
        initViews();
    }

    private void initViews() {
        mInflater = LayoutInflater.from(getContext());
        mheardView = mInflater.inflate(R.layout.list_reflash_heard_item, null);
        this.addHeaderView(mheardView);

        ivArrow = (ImageView) mheardView.findViewById(R.id.iv_arr);
        tvTitle = (TextView) mheardView.findViewById(R.id.tv_title);
        tvTime = (TextView) mheardView.findViewById(R.id.tv_date);
        pbProgress = (ProgressBar) mheardView.findViewById(R.id.pb_progress);

        measureView(mheardView);
        mhearderHeight = mheardView.getMeasuredHeight();
        Log.d("tag", "mhearderHeight:" + mhearderHeight);
        topPadding(-mhearderHeight);
        addHeaderView(mheardView, null, false);// 将下拉布局加入listView顶部
        setOnScrollListener(this);
        initArrowAnim();
    }

    /**
     * 设置mheardView布局的上边距
     * 
     * @param i
     */
    private void topPadding(int i) {
        mheardView.setPadding(mheardView.getPaddingLeft(), i,
                mheardView.getPaddingRight(), mheardView.getPaddingBottom());
        mheardView.invalidate(); // 重新绘制mheardView

    }

    /**
     * 通知父布局headerView的尺寸(便于后面测量headerView的高度)
     * 
     * @param child
     */
    private void measureView(View child) {
        ViewGroup.LayoutParams params = child.getLayoutParams();
        if (params == null) {
            params = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        // 1.左右边距 2.内边距 3.子布局宽度
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
        int lpHeight = params.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
                    MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0,
                    MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        if (firstVisibleItem == 0) {
            isreflash = true;
        } else {
            isreflash = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            if (startY == -1) {// 确保startY有效
                startY = (int) ev.getRawY();
            }
            if (state == REFRESHING) {// 正在刷新
                break;
            }
            int tempY = (int) ev.getY();
            int dy = tempY - startY; // 偏移量
            Log.d("tag", "偏移量:" + dy);
            if (dy > 0) {
                int pading = dy - mhearderHeight;
                topPadding(pading);
                if (pading > 0 && state != RELEASE_REFRESH) {
                    state = RELEASE_REFRESH;
                    topPadding(0);
                    refreshState();
                } else if (pading < 0 && state != PULL_To_REFRESH) {
                    state = PULL_To_REFRESH;
                    refreshState();
                }
                return true;
            }

            break;
        case MotionEvent.ACTION_UP:
            startY = -1;// 重置

            if (state == RELEASE_REFRESH) {
                state = REFRESHING;// 正在刷新
                topPadding(0);
                refreshState();
            } else if (state == PULL_To_REFRESH) {
                topPadding(-mhearderHeight);
            }

            break;

        default:
            break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 通过State值改变hearerView状态
     */
    private void refreshState() {
        switch (state) {
        case PULL_To_REFRESH:
            tvTitle.setText("下拉刷新");
            ivArrow.setVisibility(View.VISIBLE);
            pbProgress.setVisibility(View.INVISIBLE);
            ivArrow.startAnimation(animDown);
            break;
        case RELEASE_REFRESH:
            tvTitle.setText("松开刷新");
            ivArrow.setVisibility(View.VISIBLE);
            pbProgress.setVisibility(View.INVISIBLE);
            ivArrow.startAnimation(animUp);
            break;
        case REFRESHING:
            tvTitle.setText("正在刷新...");
            ivArrow.clearAnimation();// 必须先清除动画,才能隐藏
            ivArrow.setVisibility(View.INVISIBLE);
            pbProgress.setVisibility(View.VISIBLE);

            break;

        default:
            break;
        }
    }

    /**
     * 初始化箭头动画
     */
    private void initArrowAnim() {
        animUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        animUp.setDuration(200);
        animUp.setFillAfter(true);

        animDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
                0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        animDown.setDuration(200);
        animDown.setFillAfter(true);

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值