自定义下拉刷新ListView的CustomListView原理小分析

总结:下拉刷新是监控了ListView的onTouchEvent这个事件,计算滑动的距离,动态设置listview头部的padding,

header.setPadding立即:如果top是正值,那么top边就向上跑,形成一段空隙,如果top为负值,top边就向下跑,这样就湮没了头部的顶部,

其他情况类似,先理解正值往哪里跑,再理解负值,往反方向跑


还有一点设置padding可能会引起控件高度和宽度的变化的



package com.example.customview;


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

/**
 * Created by dream on 2015/11/2.
 */
public class CustomListView extends ListView {
    View header;
    int viewHeight;

    ProgressBar progressBar;
    ImageView ivArror;
    TextView tvState;
    byte currentState;
    public static final byte STATE_DONE = 0;
    public static final byte STATE_PULL = 1;
    public static final byte STATE_RELEASE = 2;
    public static final byte STATE_REFRESHING = 3;

    int downY;
    OnRefreshListener onRefreshListener;

    /**
     *
     * @param onRefreshListener
     *            实现类
     */
    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        this.onRefreshListener = onRefreshListener;
    }

    public CustomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        header = inflate(context,R.layout.listview_header,null);
        this.addHeaderView(header);
        progressBar = (ProgressBar) header.findViewById(R.id.progressBar);
        ivArror = (ImageView) header.findViewById(R.id.iv_arrow);
        tvState = (TextView) header.findViewById(R.id.tv_state);
        //getHeight 要求控件必须显示在屏幕上
        //没显示,先测量,再getMeasuredHeight
        header.measure(0, 0);
        viewHeight=header.getMeasuredHeight();
        Log.i("viewHeight", "" + viewHeight);
        header.setPadding(0, 0, 0, -viewHeight);

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        try {
            switch(action){
                case MotionEvent.ACTION_DOWN:
                    if(this.currentState==STATE_DONE){
                        this.currentState=STATE_PULL;
                        this.downY = (int) ev.getY();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(this.currentState==STATE_PULL){
                        int moveY = (int) ev.getY();
                        int top = -viewHeight + moveY- downY;

                        header.setPadding(0, 0, 0, top); //动态设置header的padding(每次设置都从0,0,0,0 效果开始出发考虑变化)
                        if (moveY - downY > viewHeight) {
                            this.currentState = STATE_RELEASE;
                            tvState.setText("松开刷新");
                        }

                    }
                    break;
                case MotionEvent.ACTION_UP:
                   int h = header.getMeasuredHeight();
                    if (this.currentState == STATE_RELEASE) {
                        this.currentState = STATE_REFRESHING;
                        tvState.setText("刷新中"+h);
                        ivArror.setVisibility(View.GONE);
                        progressBar.setVisibility(VISIBLE);
                    if (onRefreshListener != null) {
                        onRefreshListener.onRefresh(this);
                    }
                    }
                    break;
            }
        }catch(Exception e){
            e.printStackTrace();
        }


        return super.onTouchEvent(ev);
    }

    public void refreshComplete() {
        progressBar.setVisibility(View.GONE);
        ivArror.setVisibility(View.VISIBLE);
        tvState.setText("下拉刷新");
        header.setPadding(0, -viewHeight, 0, 0);
        this.currentState = STATE_DONE;
    }
    interface OnRefreshListener {
        public void onRefresh(CustomListView customListView);
    }
}

你可能感兴趣的:(自定义下拉刷新ListView的CustomListView原理小分析)