随着现在Android设备的越来越多,各种应用层出不穷,下拉刷新这种基本上每个应用都必备的东西也被人玩出了各种花样了。

一开始下拉刷新都这这样的(XListView):

Android app设置刷新率自动 安卓 自适应刷新_自定义

不过这样子做,只支持ListView 并且对ListView的侵入太深,所有很快就被摒弃了,演变成了这样

Android app设置刷新率自动 安卓 自适应刷新_Android app设置刷新率自动_02

chrisbanes/Android-PullToRefresh库,这个就太牛逼了,可以支持ListView、ExpandableListView、GridView、WebView、ScrollView、HorizontalScrollView、ViewPager、ListFragment、、、

再然后随着大家的要求越来越高,追求个性的状态,已经不再满足这样单调的刷新样式。

在后面就被大家玩坏了,各种各样的奇葩效果,有这样的

也有这样的

包括google本身也有了下拉刷新控件SwipeRefreshLayout。

Android app设置刷新率自动 安卓 自适应刷新_下拉刷新_03


虽然刷新控件的种类繁多,不过万变不离其宗,下拉刷新的原理以及对触摸事件的处理方式总是不变的。如果每做一个项目为了不同的刷新效果还需要我们总要再去做这些重复的劳动未免有点太不符合我们这些懒惰的程序员思想。我基于Yalantis公司开发的下拉刷新开源控件做了一些修改,实现可自定义下拉刷新样式的RefreshView。
先上部分代码:

//对于状态的判定
 //静止状态
    private static final int NORMAL = 11;
    //用户正在下拉,但还没有到达刷新的位置
    private static final int BEGIN_DOWN = 12;
    //到达可以刷新的位置,但用户还没有松开手指
    private static final int CAN_REFRESH = 13;
    //正在刷新
    private static final int BEGIN_REFRESH = 14;
    //刷新完成
    private static final int REFRESH_COMPLATE = 15;
//定义的RefreshView接口类
/**
 * Created by Sunday on 16/2/1.
 * 刷新头样式
 */
public abstract class RefreshView extends FrameLayout {
    private Context mContext;

    public RefreshView(Context context) {
        super(context);
        this.mContext = context;
    }

    /**
     * 静止状态
     */
    public abstract void normal();

    /**
     * 用户正在下拉,但还没有到达刷新的位置
     * @param downRate 下拉与指定刷新位置的比例 最大为1(为1时已经入canRefresh方法中)  可根据此比例自定义刷新动画
     */
    public abstract void beginDown(float downRate);

    /**
     * 到达可以刷新的位置,但用户还没有松开手指
     */
    public abstract void canRefresh();

    /**
     * 正在刷新
     */
    public abstract void beginRefresh();

    /**
     * 刷新完成
     */
    public abstract void refreshComplete();

}

通过集成该类,即可实现自定义的下拉刷新界面,具体集成方式如下。

/**
 * Created by Sunday on 16/2/1.
 * 默认的刷新头样式
 */
public class DefaultRefeshView extends RefreshView {

    private LinearLayout mLinearLayout;
    private ImageView mImageView;
    private TextView mTextView;
    private RotateAnimation rotateAnimation;
    private boolean isRefresh;

    public DefaultRefeshView(Context context) {
        super(context);

        mLinearLayout = new LinearLayout(context);
        mLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
        mLinearLayout.setGravity(Gravity.CENTER);

        mImageView = new ImageView(context);
        mTextView = new TextView(context);
        mTextView.setTextSize(12);
        mTextView.setTextColor(getResources().getColor(R.color.default_text_color));

        mLinearLayout.addView(mImageView);
        mLinearLayout.addView(mTextView);

        addView(mLinearLayout);
    }

    @Override
    public void normal() {
        mImageView.setRotation(0);
        mImageView.setImageResource(R.drawable.ic_default_refresh);
        mTextView.setText("下拉可刷新");
        mImageView.clearAnimation();
    }


    @Override
    public void beginDown(float downRate) {
        Log.d("TAG","downRate="+downRate);
        if (isRefresh){
            isRefresh = false;
            rotateAnimation = new RotateAnimation(180,0,mImageView.getWidth() / 2,mImageView.getHeight() / 2);
            rotateAnimation.setDuration(500);
            rotateAnimation.setFillAfter(true);
            mImageView.startAnimation(rotateAnimation);
        }
        mTextView.setText("继续下拉可刷新");
    }

    @Override
    public void canRefresh() {

        rotateAnimation = new RotateAnimation(0,180,mImageView.getWidth() / 2,mImageView.getHeight() / 2);
        rotateAnimation.setDuration(500);
        rotateAnimation.setFillAfter(true);
        mImageView.startAnimation(rotateAnimation);
        isRefresh = true;

        mTextView.setText("松开手指即可刷新");
    }

    @Override
    public void beginRefresh() {
        mImageView.setImageResource(R.drawable.ic_default_loading);
        rotateAnimation = new RotateAnimation(0,359,mImageView.getWidth() / 2,mImageView.getHeight() / 2);
        rotateAnimation.setInterpolator(new LinearInterpolator());
        rotateAnimation.setDuration(1200);
        rotateAnimation.setRepeatCount(Animation.INFINITE);
        mImageView.startAnimation(rotateAnimation);


        mTextView.setText("正在刷新");
    }

    @Override
    public void refreshComplete() {
        mImageView.setImageResource(0);
        mTextView.setText("刷新完成");

    }
}

此控件可通过,集成RefreshView,调用mPullToRefresh.setRefresh()方法,通过downRate可得到下拉与指定刷新位置的比例,即可实现自定义的刷新动画效果。此PullToRefershView继承ViewGroup理论上可支持任何控件的完成刷新效果。
到目前为止,只完成了 下拉刷新效果的自定义功能,到底部加载更多的功能,坚持着不对子View侵入的原则到现在一直没有好的实现方法