年少的时候,觉得孤单是很酷的一件事。长大以后,觉得孤单是很凄凉的一件事。现在,我觉得孤单不是一件事。有时候,人所需要的是真正的绝望。真正的绝望跟痛苦、跟悲伤都没有什么关系,真正的绝望让人心平气和。


MainActivity.java代码:

package siso.refreshablev;

import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import refreshableview.RefreshableView;
import refreshableview.refreshablehelper.RefreshableHelper;

public class MainActivity extends Activity implements View.OnClickListener {
    private static final String TAG = MainActivity.class.getSimpleName();

    private RefreshableView refreshableView;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.main_tv).setOnClickListener(this);
        refreshableView = (RefreshableView) findViewById(R.id.main_refresh_view);
        refreshableView.setRefreshableHelper(new RefreshableHelper() {

            @Override
            public View onInitRefreshHeaderView() {
                return LayoutInflater.from(MainActivity.this).inflate(R.layout.refresh_head, null);
            }

            @Override
            public boolean onInitRefreshHeight(int originRefreshHeight) {
                refreshableView.setRefreshNormalHeight(refreshableView.getOriginRefreshHeight() / 3);
                refreshableView.setRefreshingHeight(refreshableView.getOriginRefreshHeight());
                refreshableView.setRefreshArrivedStateHeight(refreshableView.getOriginRefreshHeight());
                return false;
            }

            @Override
            public void onRefreshStateChanged(View refreshView, int refreshState) {
                TextView tv = (TextView) refreshView.findViewById(R.id.refresh_head_tv);
                switch (refreshState) {
                    case RefreshableView.STATE_REFRESH_NORMAL:
                        tv.setText("正常状态");
                        break;
                    case RefreshableView.STATE_REFRESH_NOT_ARRIVED:
                        tv.setText("往下拉可以刷新");
                        break;
                    case RefreshableView.STATE_REFRESH_ARRIVED:
                        tv.setText("放手可以刷新");
                        break;
                    case RefreshableView.STATE_REFRESHING:
                        tv.setText("正在刷新");
                        new Thread(
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            Thread.sleep(1000l);
                                            runOnUiThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                    refreshableView.onCompleteRefresh();
                                                }
                                            });
                                        } catch (InterruptedException e) {
                                            Log.e(TAG, "_", e);
                                        }
                                    }
                                }
                        ).start();
                        break;

                }
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.main_tv:
                Log.d(TAG, "content clicked");
                startActivity(new Intent(this, RefreshableListActivity.class));
                break;
        }
    }
}

RefreshableListActivity.java代码:

package siso.refreshablev;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TextView;


import java.util.ArrayList;
import java.util.List;

import refreshableview.RefreshableListView;
import refreshableview.RefreshableView;
import refreshableview.refreshablehelper.RefreshableHelper;


public class RefreshableListActivity extends Activity {
    private static final String TAG = RefreshableListActivity.class.getSimpleName();
    RefreshableListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.refreshable_list);
        lv = (RefreshableListView) findViewById(R.id.refreshable_lv);
        lv.setRefreshableHelper(new RefreshableHelper() {

            @Override
            public View onInitRefreshHeaderView() {
                return LayoutInflater.from(RefreshableListActivity.this).inflate(R.layout.refresh_head, null);
            }

            @Override
            public boolean onInitRefreshHeight(int originRefreshHeight) {
                lv.setRefreshNormalHeight(lv.getOriginRefreshHeight() / 3);
                lv.setRefreshingHeight(lv.getOriginRefreshHeight());
                lv.setRefreshArrivedStateHeight(lv.getOriginRefreshHeight());
                return false;
            }

            @Override
            public void onRefreshStateChanged(View refreshView, int refreshState) {
                TextView tv = (TextView) refreshView.findViewById(R.id.refresh_head_tv);
                switch (refreshState) {
                    case RefreshableView.STATE_REFRESH_NORMAL:
                        tv.setText("正常状态");
                        break;
                    case RefreshableView.STATE_REFRESH_NOT_ARRIVED:
                        tv.setText("往下拉可以刷新");
                        break;
                    case RefreshableView.STATE_REFRESH_ARRIVED:
                        tv.setText("放手可以刷新");
                        break;
                    case RefreshableView.STATE_REFRESHING:
                        tv.setText("正在刷新");
                        new Thread(
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            Thread.sleep(1000l);
                                            runOnUiThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                    lv.onCompleteRefresh();
                                                }
                                            });
                                        } catch (InterruptedException e) {
                                            Log.e(TAG, "_", e);
                                        }
                                    }
                                }
                        ).start();
                        break;

                }
            }
        });

        List<String> data = new ArrayList<String>();
        for (int i = 0; i < 30; i++) {
            data.add("item_" + i);
        }
        ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
        lv.setAdapter(adapter);
        adapter.notifyDataSetChanged();

    }


}

NestScrollView.java代码:

package refreshableview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewParent;
import android.widget.ScrollView;


public class NestScrollView extends ScrollView {
    private static final String TAG = NestScrollView.class.getSimpleName();

    public NestScrollView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d(TAG, "___[dispatchTouchEvent]ev action: " + ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        super.onInterceptTouchEvent(ev);
        Log.d(TAG, "___[onInterceptTouchEvent]ev action: " + ev.getAction());
        if (MotionEvent.ACTION_MOVE == ev.getAction()) {
            return true;
        }
        return false;
    }

    float lastDownY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastDownY = event.getY();
                parentRequestDisallowInterceptTouchEvent(true); // 保证事件可往下传递
                Log.d(TAG, "___Down");
                return true;
//                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "___move, this.getScrollY(): " + this.getScrollY());
                boolean isTop = event.getY() - lastDownY > 0 && this.getScrollY() == 0;
                if (isTop) { // 允许父控件拦截,即不允许父控件拦截设为false
                    parentRequestDisallowInterceptTouchEvent(false);
                    return false;
                } else { // 不允许父控件拦截,即不允许父控件拦截设为true
                    parentRequestDisallowInterceptTouchEvent(true);
                    return true;
                }
//                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "___up, this.getScrollY(): " + this.getScrollY());
                parentRequestDisallowInterceptTouchEvent(true); // 保证事件可往下传递
                break;
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "___cancel");
                break;
        }
        return false;
    }

    /**
     * 是否允许父控件拦截事件
     * @param disallowIntercept
     */
    private void parentRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        ViewParent vp = getParent();
        if (null == vp) {
            return;
        }
        vp.requestDisallowInterceptTouchEvent(disallowIntercept);
    }

}

RefreshableListView.java代码:

package refreshableview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ListAdapter;
import android.widget.ListView;

import refreshableview.refreshablehelper.RefreshableHelper;


public class RefreshableListView extends ListView {
    private static final String TAG = RefreshableListView.class.getSimpleName();

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

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

    public RefreshableListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    /**
     * 刷新状态
     */
    public static final int STATE_REFRESH_NORMAL = 0x21;
    public static final int STATE_REFRESH_NOT_ARRIVED = 0x22;
    public static final int STATE_REFRESH_ARRIVED = 0x23;
    public static final int STATE_REFRESHING = 0x24;
    private int refreshState;
    // 刷新状态监听
    private RefreshableHelper refreshableHelper;
    /**
     * 刷新的view
     */
    private View refreshHeaderView;
    /**
     * 刷新的view的真实高度
     */
    private int originRefreshHeight;
    /**
     * 有效下拉刷新需要达到的高度
     */
    private int refreshArrivedStateHeight;
    /**
     * 刷新时显示的高度
     */
    private int refreshingHeight;
    /**
     * 正常未刷新高度
     */
    private int refreshNormalHeight;

    public void setRefreshableHelper(RefreshableHelper refreshableHelper) {
        this.refreshableHelper = refreshableHelper;
    }

    private Context context;

    private void init(Context context) {
        this.context = context;

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.d(TAG, "[onSizeChanged]w: " + w + ", h: " + h);
        Log.d(TAG, "[onSizeChanged]oldw: " + oldw + ", oldh: " + oldh);
        Log.d(TAG, "[onSizeChanged]child counts: " + this.getChildCount());

    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        if (null == refreshHeaderView) {
            addHeaderView();
        }
        super.setAdapter(adapter);
    }

    private void addHeaderView() {
        if (null != refreshableHelper) {
            refreshHeaderView = refreshableHelper.onInitRefreshHeaderView();
        }
        if (null == refreshHeaderView) {
            Log.e(TAG, "refreshHeaderView is null!");
            return;
        }
        this.addHeaderView(refreshHeaderView);
        // 计算refreshHeadView尺寸
        int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        refreshHeaderView.measure(width, expandSpec);

        originRefreshHeight = refreshHeaderView.getMeasuredHeight();

        boolean isUseDefault = true;
        if (null != refreshableHelper) {
            isUseDefault = refreshableHelper.onInitRefreshHeight(originRefreshHeight);
        }

        // 初始化各个高度
        if (isUseDefault) {
            refreshArrivedStateHeight = originRefreshHeight;
            refreshingHeight = originRefreshHeight;
            refreshNormalHeight = 0;
        }
        Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
        changeViewHeight(refreshHeaderView, refreshNormalHeight);

        // 初始化为正常状态
        setRefreshState(STATE_REFRESH_NORMAL);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        super.dispatchTouchEvent(ev);
//        if(MotionEvent.ACTION_MOVE == ev.getAction()){
//            return true;
//        }
//        return false;
        return true;
    }

    private float lastDownY = Float.MAX_VALUE;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
//        super.onTouchEvent(ev);
        Log.d(TAG, "[onTouchEvent]ev action: " + ev.getAction());
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                super.onTouchEvent(ev);
                lastDownY = ev.getY();
                Log.d(TAG, "Down --> lastDownY: " + lastDownY);
                break;
            case MotionEvent.ACTION_MOVE:
                float curY = ev.getY();
                float deltaY = curY - lastDownY;
                Log.d(TAG, "Move --> deltaY(curY - downY): " + deltaY);

                int curHeight = refreshHeaderView.getMeasuredHeight();
                int exceptHeight = curHeight + (int) (deltaY / 2);

//                boolean isTop = this.getScrollY() == 0;
                boolean isTop = 0 == this.getChildAt(0).getTop();
                boolean isDropDown = curY - lastDownY > 0;
                Log.d(TAG, "isTop: " + isTop + ", getTop(): " + this.getChildAt(0).getTop());
                if (isTop) {
                    if (refreshState == STATE_REFRESH_NORMAL && !isDropDown) { // 正常状态,手指往上(列表往下滚动)
                        super.onTouchEvent(ev);
                    } else {
                        // 如果当前没有处在正在刷新状态,则更新刷新状态
                        if (STATE_REFRESHING != refreshState) {
                            if (curHeight >= refreshArrivedStateHeight) { // 达到可刷新状态
                                setRefreshState(STATE_REFRESH_ARRIVED);
                            } else if (curHeight == refreshNormalHeight) { // 正常状态
                                setRefreshState(STATE_REFRESH_NORMAL);
                            } else { // 未达到可刷新状态
                                setRefreshState(STATE_REFRESH_NOT_ARRIVED);
                            }
                            changeViewHeight(refreshHeaderView, Math.max(refreshNormalHeight, exceptHeight));
                        } else {
                            super.onTouchEvent(ev);
                        }

                    }

                } else {
                    super.onTouchEvent(ev);
                }
                lastDownY = curY;
                break;
            case MotionEvent.ACTION_UP:
                super.onTouchEvent(ev);
                lastDownY = Float.MAX_VALUE;
                Log.d(TAG, "Up --> lastDownY: " + lastDownY);
                // 如果是达到刷新状态,则设置正在刷新状态的高度
                if (STATE_REFRESH_ARRIVED == refreshState) { // 达到了刷新的状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
                    setRefreshState(STATE_REFRESHING);
                } else if (STATE_REFRESHING == refreshState) { // 正在刷新的状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
                } else {
                    // 执行动画后回归正常状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
                }
                break;
        }
        return true;
    }


    /**
     * 刷新完毕后调用此方法
     */
    public void onCompleteRefresh() {
        if (STATE_REFRESHING == refreshState) {
            setRefreshState(STATE_REFRESH_NORMAL);
            startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
        }
    }

    /**
     * 修改当前的刷新状态
     *
     * @param expectRefreshState
     */
    private void setRefreshState(int expectRefreshState) {
        if (expectRefreshState != refreshState) {
            refreshState = expectRefreshState;
            if (null != refreshableHelper) {
                refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
            }
        }
    }


    /**
     * 改变某控件的高度
     *
     * @param view
     * @param height
     */
    private void changeViewHeight(View view, int height) {
        Log.d(TAG, "[changeViewHeight]change Height: " + height);
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        if (null == lp) {
            lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
        }
        lp.height = height;
        view.setLayoutParams(lp);
    }

    /**
     * 改变某控件的高度动画
     *
     * @param view
     * @param fromHeight
     * @param toHeight
     */
    private void startHeightAnimation(final View view, int fromHeight, int toHeight) {
        startHeightAnimation(view, fromHeight, toHeight, null);
    }

    private void startHeightAnimation(final View view, int fromHeight, int toHeight, Animator.AnimatorListener animatorListener) {
        if (toHeight == view.getMeasuredHeight()) {
            return;
        }
        ValueAnimator heightAnimator = ValueAnimator.ofInt(fromHeight, toHeight);
        heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                Integer value = (Integer) valueAnimator.getAnimatedValue();
                if (null == value) return;
                changeViewHeight(view, value);
            }
        });
        if (null != animatorListener) {
            heightAnimator.addListener(animatorListener);
        }
        heightAnimator.setInterpolator(new LinearInterpolator());
        heightAnimator.setDuration(300/*ms*/);
        heightAnimator.start();
    }

    AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            setRefreshState(STATE_REFRESH_NORMAL); // 回归正常状态
        }
    };

    public void setRefreshArrivedStateHeight(int refreshArrivedStateHeight) {
        this.refreshArrivedStateHeight = refreshArrivedStateHeight;
    }

    public void setRefreshingHeight(int refreshingHeight) {
        this.refreshingHeight = refreshingHeight;
    }

    public void setRefreshNormalHeight(int refreshNormalHeight) {
        this.refreshNormalHeight = refreshNormalHeight;
    }

    public int getOriginRefreshHeight() {
        return originRefreshHeight;
    }

}

RefreshableView.java代码:

package refreshableview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;

import refreshableview.refreshablehelper.RefreshableHelper;
import siso.refreshablev.R;

public class RefreshableView extends LinearLayout {
    private static final String TAG = RefreshableView.class.getSimpleName();

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

    public RefreshableView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.refreshableView);
        for (int i = 0, len = a.length(); i < len; i++) {
            int attrIndex = a.getIndex(i);
            switch (attrIndex) {
                case R.styleable.refreshableView_interceptAllMoveEvents:
                    interceptAllMoveEvents = a.getBoolean(i, false);
                    break;
            }
        }
        a.recycle();

        init(context);
    }

    public RefreshableView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    /**
     * 刷新状态
     */
    public static final int STATE_REFRESH_NORMAL = 0x21;
    public static final int STATE_REFRESH_NOT_ARRIVED = 0x22;
    public static final int STATE_REFRESH_ARRIVED = 0x23;
    public static final int STATE_REFRESHING = 0x24;
    private int refreshState;
    // 刷新状态监听
    private RefreshableHelper refreshableHelper;

    public void setRefreshableHelper(RefreshableHelper refreshableHelper) {
        this.refreshableHelper = refreshableHelper;
    }

    private Context context;
    /**
     * 刷新的view
     */
    private View refreshHeaderView;
    /**
     * 刷新的view的真实高度
     */
    private int originRefreshHeight;
    /**
     * 有效下拉刷新需要达到的高度
     */
    private int refreshArrivedStateHeight;
    /**
     * 刷新时显示的高度
     */
    private int refreshingHeight;
    /**
     * 正常未刷新高度
     */
    private int refreshNormalHeight;


    /**
     * 默认不允许拦截(即,往子view传递事件),该属性只有在interceptAllMoveEvents为false的时候才有效
     */
    private boolean disallowIntercept = true;
    /**
     * xml中可设置它的值为false,表示不把移动的事件传递给子控件
     */
    private boolean interceptAllMoveEvents;

    private void init(Context context) {
        this.context = context;
        this.setOrientation(VERTICAL);

//        Log.d(TAG, "[init]originRefreshHeight: " + refreshHeaderView.getMeasuredHeight());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (null != refreshableHelper) {
            refreshHeaderView = refreshableHelper.onInitRefreshHeaderView();
        }
//        refreshHeaderView = LayoutInflater.from(context).inflate(R.layout.refresh_head, null);
        if (null == refreshHeaderView) {
            Log.e(TAG, "refreshHeaderView is null!");
            return;
        }
        this.removeView(refreshHeaderView);
        this.addView(refreshHeaderView, 0);

        // 计算refreshHeadView尺寸
        int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        refreshHeaderView.measure(width, expandSpec);

        Log.d(TAG, "[onSizeChanged]w: " + w + ", h: " + h);
        Log.d(TAG, "[onSizeChanged]oldw: " + oldw + ", oldh: " + oldh);
        Log.d(TAG, "[onSizeChanged]child counts: " + this.getChildCount());
        originRefreshHeight = refreshHeaderView.getMeasuredHeight();

        boolean isUseDefault = true;
        if (null != refreshableHelper) {
            isUseDefault = refreshableHelper.onInitRefreshHeight(originRefreshHeight);
        }

        // 初始化各个高度
        if (isUseDefault) {
            refreshArrivedStateHeight = originRefreshHeight;
            refreshingHeight = originRefreshHeight;
            refreshNormalHeight = 0;
        }
        Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
        changeViewHeight(refreshHeaderView, refreshNormalHeight);

        // 初始化为正常状态
        setRefreshState(STATE_REFRESH_NORMAL);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d(TAG, "[dispatchTouchEvent]ev action: " + ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d(TAG, "[onInterceptTouchEvent]ev action: " + ev.getAction());
        if (!interceptAllMoveEvents) {
            return !disallowIntercept;
        }
        // 如果设置了拦截所有move事件,即interceptAllMoveEvents为true
        if (MotionEvent.ACTION_MOVE == ev.getAction()) {
            return true;
        }
        return false;
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        if (this.disallowIntercept == disallowIntercept) {
            return;
        }
        this.disallowIntercept = disallowIntercept;
        super.requestDisallowInterceptTouchEvent(disallowIntercept);
    }

    private float downY = Float.MAX_VALUE;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        super.onTouchEvent(event);
        Log.d(TAG, "[onTouchEvent]ev action: " + event.getAction());
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = event.getY();
                Log.d(TAG, "Down --> downY: " + downY);
                requestDisallowInterceptTouchEvent(true); // 保证事件可往下传递
                break;
            case MotionEvent.ACTION_MOVE:

                float curY = event.getY();
                float deltaY = curY - downY;
                // 是否是有效的往下拖动事件(则需要显示加载header)
                boolean isDropDownValidate = Float.MAX_VALUE != downY;
                /**
                 * 修改拦截设置
                 * 如果是有效往下拖动事件,则事件需要在本ViewGroup中处理,所以需要拦截不往子控件传递,即不允许拦截设为false
                 * 如果不是有效往下拖动事件,则事件传递给子控件处理,所以不需要拦截,并往子控件传递,即不允许拦截设为true
                 */
                requestDisallowInterceptTouchEvent(!isDropDownValidate);

                downY = curY;
                Log.d(TAG, "Move --> deltaY(curY - downY): " + deltaY);
                int curHeight = refreshHeaderView.getMeasuredHeight();
                int exceptHeight = curHeight + (int) (deltaY / 2);

                // 如果当前没有处在正在刷新状态,则更新刷新状态
                if (STATE_REFRESHING != refreshState) {
                    if (curHeight >= refreshArrivedStateHeight) { // 达到可刷新状态
                        setRefreshState(STATE_REFRESH_ARRIVED);
                    } else { // 未达到可刷新状态
                        setRefreshState(STATE_REFRESH_NOT_ARRIVED);
                    }
                }
                if (isDropDownValidate) {
                    changeViewHeight(refreshHeaderView, Math.max(refreshNormalHeight, exceptHeight));
                } else { // 防止从子控件修改拦截后引发的downY为Float.MAX_VALUE的问题
                    changeViewHeight(refreshHeaderView, Math.max(curHeight, exceptHeight));
                }

                break;
            case MotionEvent.ACTION_UP:
                downY = Float.MAX_VALUE;
                Log.d(TAG, "Up --> downY: " + downY);
                requestDisallowInterceptTouchEvent(true); // 保证事件可往下传递
                // 如果是达到刷新状态,则设置正在刷新状态的高度
                if (STATE_REFRESH_ARRIVED == refreshState) { // 达到了刷新的状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
                    setRefreshState(STATE_REFRESHING);
                } else if (STATE_REFRESHING == refreshState) { // 正在刷新的状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
                } else {
                    // 执行动画后回归正常状态
                    startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
                }

                break;
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "cancel");
                break;
        }
        return true;
    }

    /**
     * 刷新完毕后调用此方法
     */
    public void onCompleteRefresh() {
        if (STATE_REFRESHING == refreshState) {
            setRefreshState(STATE_REFRESH_NORMAL);
            startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
        }
    }

    /**
     * 修改当前的刷新状态
     *
     * @param expectRefreshState
     */
    private void setRefreshState(int expectRefreshState) {
        if (expectRefreshState != refreshState) {
            refreshState = expectRefreshState;
            if (null != refreshableHelper) {
                refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
            }
        }
    }


    /**
     * 改变某控件的高度
     *
     * @param view
     * @param height
     */
    private void changeViewHeight(View view, int height) {
        Log.d(TAG, "[changeViewHeight]change Height: " + height);
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        lp.height = height;
        view.setLayoutParams(lp);
    }

    /**
     * 改变某控件的高度动画
     *
     * @param view
     * @param fromHeight
     * @param toHeight
     */
    private void startHeightAnimation(final View view, int fromHeight, int toHeight) {
        startHeightAnimation(view, fromHeight, toHeight, null);
    }

    private void startHeightAnimation(final View view, int fromHeight, int toHeight, Animator.AnimatorListener animatorListener) {
        if (toHeight == view.getMeasuredHeight()) {
            return;
        }
        ValueAnimator heightAnimator = ValueAnimator.ofInt(fromHeight, toHeight);
        heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                Integer value = (Integer) valueAnimator.getAnimatedValue();
                if (null == value) return;
                changeViewHeight(view, value);
            }
        });
        if (null != animatorListener) {
            heightAnimator.addListener(animatorListener);
        }
        heightAnimator.setInterpolator(new LinearInterpolator());
        heightAnimator.setDuration(300/*ms*/);
        heightAnimator.start();
    }

    AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            setRefreshState(STATE_REFRESH_NORMAL); // 回归正常状态
        }
    };

    public void setRefreshArrivedStateHeight(int refreshArrivedStateHeight) {
        this.refreshArrivedStateHeight = refreshArrivedStateHeight;
    }

    public void setRefreshingHeight(int refreshingHeight) {
        this.refreshingHeight = refreshingHeight;
    }

    public void setRefreshNormalHeight(int refreshNormalHeight) {
        this.refreshNormalHeight = refreshNormalHeight;
    }

    public int getOriginRefreshHeight() {
        return originRefreshHeight;
    }
}

RefreshableHelper.java代码:

package refreshableview.refreshablehelper;

import android.view.View;


public interface RefreshableHelper {
    /**
     * 初始化刷新View
     *
     * @return
     */
    View onInitRefreshHeaderView();

    /**
     * 初始化各个尺寸高度
     *
     * @param originRefreshHeight
     * @return
     */
    boolean onInitRefreshHeight(int originRefreshHeight);

    /**
     * 刷新状态改变
     *
     * @param refreshView
     * @param refreshState
     */
    void onRefreshStateChanged(View refreshView, int refreshState);
}

main.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:rv="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <refreshableview.RefreshableView
            android:id="@+id/main_refresh_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            rv:interceptAllMoveEvents="false"
            >
        <refreshableview.NestScrollView android:layout_width="match_parent" android:layout_height="wrap_content"
                android:fillViewport="true"
                >

            <TextView
                    android:id="@+id/main_tv"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:padding="20dp"
                    android:textSize="18sp"
                    android:text="下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新---下拉刷新\n\n\n\n\n\n\n\n\n\n\n"
                    />

        </refreshableview.NestScrollView>
    </refreshableview.RefreshableView>

</LinearLayout>

activity_refreshable_list.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="siso.refreshablev.RefreshableListActivity">

</RelativeLayout>

refresh_head.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="70dp"
              android:gravity="center"
              android:background="#aa000000"
        >
    <TextView
            android:id="@+id/refresh_head_tv"
            android:layout_width="fill_parent"
            android:layout_height="70dp"
            android:gravity="center"
            android:background="#aabbcc"
            android:textSize="18sp"
            android:text="refreshing"
            />

</LinearLayout>

refreshable_list.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">


    <refreshableview.RefreshableListView
            android:id="@+id/refreshable_lv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:cacheColorHint="@android:color/transparent"
            />

</LinearLayout>

运行结果如图:

Android 一秒一刷新_Android 一秒一刷新


Android 一秒一刷新_ide_02


Android 一秒一刷新_android_03