欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

适用各个布局的自定义下拉刷新,布局自定义下拉

来源: 开发者 投稿于  被查看 31568 次 评论:258

适用各个布局的自定义下拉刷新,布局自定义下拉


随着android 版本的更新换代,android系统都自带刷新了。

然而还不够炫,我接下来给大家动画版的下拉刷新:水滴下拉刷新,有什么问题请及时反馈,好修改

效果图如下:



自定义类 定义了刷新的方法。如果有需要加载更多可自行修改。

该demo 是我从其他地方下载下来的,感谢原作者的分享!

代码贴下,好了解:

package com.tuesda.walker.circlerefresh;


import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;


import com.tuesda.circlerefreshlayout.R;


/**
 * Created by zhanglei on 15/7/20.
 */
@SuppressLint("NewApi")
public class CircleRefreshLayout extends FrameLayout {


    @SuppressWarnings("unused")
private static String TAG = "pullToRefresh";


    private static final long BACK_TOP_DUR = 600;
    private static final long REL_DRAG_DUR = 200;


    private int mHeaderBackColor = 0xff8b90af;
    private int mHeaderForeColor = 0xffffffff;
    private int mHeaderCircleSmaller = 6;




    private float mPullHeight;
    private float mHeaderHeight;
    private View mChildView;
    private AnimationView mHeader;


    private boolean mIsRefreshing;


    private float mTouchStartY;


    private float mTouchCurY;


    private ValueAnimator mUpBackAnimator;
    private ValueAnimator mUpTopAnimator;


    private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(10);


    public CircleRefreshLayout(Context context) {
        this(context, null, 0);
    }


    public CircleRefreshLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public CircleRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }


    private void init(Context context, AttributeSet attrs, int defStyleAttr) {


        if (getChildCount() > 1) {
            throw new RuntimeException("you can only attach one child");
        }
        setAttrs(attrs);
        mPullHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, context.getResources().getDisplayMetrics());
        mHeaderHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, context.getResources().getDisplayMetrics());


        this.post(new Runnable() {
            @Override
            public void run() {
                mChildView = getChildAt(0);
                addHeaderView();
            }
        });


    }


    private void setAttrs(AttributeSet attrs) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CirCleRefreshLayout);


        mHeaderBackColor = a.getColor(R.styleable.CirCleRefreshLayout_AniBackColor, mHeaderBackColor);
        mHeaderForeColor = a.getColor(R.styleable.CirCleRefreshLayout_AniForeColor, mHeaderForeColor);
        mHeaderCircleSmaller = a.getInt(R.styleable.CirCleRefreshLayout_CircleSmaller, mHeaderCircleSmaller);


        a.recycle();
    }


    private void addHeaderView() {
        mHeader = new AnimationView(getContext());
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
        params.gravity = Gravity.TOP;
        mHeader.setLayoutParams(params);


        addViewInternal(mHeader);
        mHeader.setAniBackColor(mHeaderBackColor);
        mHeader.setAniForeColor(mHeaderForeColor);
        mHeader.setRadius(mHeaderCircleSmaller);


        setUpChildAnimation();
    }


private void setUpChildAnimation() {
        if (mChildView == null) {
            return;
        }
        mUpBackAnimator = ValueAnimator.ofFloat(mPullHeight, mHeaderHeight);
        mUpBackAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float val = (Float) animation.getAnimatedValue();
                if (mChildView != null) {
                    mChildView.setTranslationY(val);
                }
            }
        });
        mUpBackAnimator.setDuration(REL_DRAG_DUR);
        mUpTopAnimator = ValueAnimator.ofFloat(mHeaderHeight, 0);
        mUpTopAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float val = (Float) animation.getAnimatedValue();
                val = decelerateInterpolator.getInterpolation(val / mHeaderHeight) * val;
                if (mChildView != null) {
                    mChildView.setTranslationY(val);
                }
                mHeader.getLayoutParams().height = (int) val;
                mHeader.requestLayout();
            }
        });
        mUpTopAnimator.setDuration(BACK_TOP_DUR);


        mHeader.setOnViewAniDone(new AnimationView.OnViewAniDone() {
            @Override
            public void viewAniDone() {
//                Log.i(TAG, "should invoke");
                mUpTopAnimator.start();
            }
        });




    }


    private void addViewInternal(@NonNull View child) {
        super.addView(child);
    }


    @Override
    public void addView(View child) {
        if (getChildCount() >= 1) {
            throw new RuntimeException("you can only attach one child");
        }


        mChildView = child;
        super.addView(child);
        setUpChildAnimation();
    }


    private boolean canChildScrollUp() {
        if (mChildView == null) {
            return false;
        }




        return ViewCompat.canScrollVertically(mChildView, -1);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mIsRefreshing) {
            return true;
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mTouchStartY = ev.getY();
                mTouchCurY = mTouchStartY;
                break;
            case MotionEvent.ACTION_MOVE:
                float curY = ev.getY();
                float dy = curY - mTouchStartY;
                if (dy > 0 && !canChildScrollUp()) {
                    return true;
                }
        }
        return super.onInterceptTouchEvent(ev);
    }


    @SuppressLint("ClickableViewAccessibility")
@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mIsRefreshing) {
            return super.onTouchEvent(event);
        }


        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mTouchCurY = event.getY();
                float dy = mTouchCurY - mTouchStartY;
                dy = Math.min(mPullHeight * 2, dy);
                dy = Math.max(0, dy);




                if (mChildView != null) {
                    float offsetY = decelerateInterpolator.getInterpolation(dy / 2 / mPullHeight) * dy / 2;
                    mChildView.setTranslationY(offsetY);


                    mHeader.getLayoutParams().height = (int) offsetY;
                    mHeader.requestLayout();
                }




                return true;


            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (mChildView != null) {
                    if (mChildView.getTranslationY() >= mHeaderHeight) {
                        mUpBackAnimator.start();
                        mHeader.releaseDrag();
                        mIsRefreshing = true;
                        if (onCircleRefreshListener!=null) {
                            onCircleRefreshListener.refreshing();
                        }


                    } else {
                        float height = mChildView.getTranslationY();
                        ValueAnimator backTopAni = ValueAnimator.ofFloat(height, 0);
                        backTopAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                            @Override
                            public void onAnimationUpdate(ValueAnimator animation) {
                                float val = (Float) animation.getAnimatedValue();
                                val = decelerateInterpolator.getInterpolation(val / mHeaderHeight) * val;
                                if (mChildView != null) {
                                    mChildView.setTranslationY(val);
                                }
                                mHeader.getLayoutParams().height = (int) val;
                                mHeader.requestLayout();
                            }
                        });
                        backTopAni.setDuration((long) (height * BACK_TOP_DUR / mHeaderHeight));
                        backTopAni.start();
                    }
                }
                return true;
            default:
                return super.onTouchEvent(event);
        }
    }


    public void finishRefreshing() {
        if (onCircleRefreshListener != null) {
            onCircleRefreshListener.completeRefresh();
        }
        mIsRefreshing = false;
        mHeader.setRefreshing(false);
    }


    private OnCircleRefreshListener onCircleRefreshListener;


    public void setOnRefreshListener(OnCircleRefreshListener onCircleRefreshListener) {
        this.onCircleRefreshListener = onCircleRefreshListener;
    }


    public interface OnCircleRefreshListener {
        void completeRefresh();


        void refreshing();
    }
}


下面这个是定义动画的显示方式。如果有更好的修改方案,可以自行修改

package com.tuesda.walker.circlerefresh;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;


/**
 * Created by zhanglei on 15/7/18.
 */
public class AnimationView extends View {


    private static final String TAG = "AnimationView";


    private int PULL_HEIGHT;
    private int PULL_DELTA;
    private float mWidthOffset;






    private AnimatorStatus mAniStatus = AnimatorStatus.PULL_DOWN;


    enum AnimatorStatus {
        PULL_DOWN,
        DRAG_DOWN,
        REL_DRAG,
        SPRING_UP, // rebound to up, the position is less than PULL_HEIGHT
        POP_BALL,
        OUTER_CIR,
        REFRESHING,
        DONE,
        STOP;


        @Override
        public String toString() {
            switch (this) {
                case PULL_DOWN:
                    return "pull down";
                case DRAG_DOWN:
                    return "drag down";
                case REL_DRAG:
                    return "release drag";
                case SPRING_UP:
                    return "spring up";
                case POP_BALL:
                    return "pop ball";
                case OUTER_CIR:
                    return "outer circle";
                case REFRESHING:
                    return "refreshing...";
                case DONE:
                    return "done!";
                case STOP:
                    return "stop";
                default:
                    return "unknown state";
            }
        }
    }




    private Paint mBackPaint;
    private Paint mBallPaint;
    private Paint mOutPaint;
    private Path mPath;




    public AnimationView(Context context) {
        this(context, null, 0);
    }


    public AnimationView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs, defStyleAttr);
    }


    private void initView(Context context, AttributeSet attrs, int defStyleAttr) {


        PULL_HEIGHT = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, context.getResources().getDisplayMetrics());
        PULL_DELTA = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
        mWidthOffset = 0.5f;// 下拉的半径
        mBackPaint = new Paint();
        mBackPaint.setAntiAlias(true);
        mBackPaint.setStyle(Paint.Style.FILL);
        mBackPaint.setColor(0xff8b90af);


        mBallPaint = new Paint();
        mBallPaint.setAntiAlias(true);
        mBallPaint.setColor(0xffffffff);
        mBallPaint.setStyle(Paint.Style.FILL);


        mOutPaint = new Paint();
        mOutPaint.setAntiAlias(true);
        mOutPaint.setColor(0xffffffff);
        mOutPaint.setStyle(Paint.Style.STROKE);
        mOutPaint.setStrokeWidth(5);//线条的宽度




        mPath = new Path();


    }


    private int mRadius;
    private int mWidth;
    private int mHeight;


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (height > PULL_DELTA + PULL_HEIGHT) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(PULL_DELTA + PULL_HEIGHT, MeasureSpec.getMode(heightMeasureSpec));
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            mRadius = getHeight() / 6;
            mWidth = getWidth();
            mHeight = getHeight();


            if (mHeight < PULL_HEIGHT) {
                mAniStatus = AnimatorStatus.PULL_DOWN;
            }




            switch (mAniStatus) {
                case PULL_DOWN:
                    if (mHeight >= PULL_HEIGHT) {
                        mAniStatus = AnimatorStatus.DRAG_DOWN;
                    }
                    break;
                case REL_DRAG:
                    break;
            }


        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        switch (mAniStatus) {
            case PULL_DOWN:
                canvas.drawRect(0, 0, mWidth, mHeight, mBackPaint);
                break;
            case REL_DRAG:
            case DRAG_DOWN:
                drawDrag(canvas);
                break;
            case SPRING_UP:
                drawSpring(canvas, getSpringDelta());
                invalidate();
                break;
            case POP_BALL:
                drawPopBall(canvas);
                invalidate();
                break;
            case OUTER_CIR:
                drawOutCir(canvas);
                invalidate();
                break;
            case REFRESHING:
                drawRefreshing(canvas);
                invalidate();
                break;
            case DONE:
                drawDone(canvas);
                invalidate();
                break;
            case STOP:
                drawDone(canvas);
                break;


        }


        if (mAniStatus == AnimatorStatus.REL_DRAG) {
            ViewGroup.LayoutParams params = getLayoutParams();
            int height;
            // NOTICE: If the height equals mLastHeight, then the requestLayout() will not work correctly
            do {
                height = getRelHeight();
            } while (height == mLastHeight && getRelRatio() != 1);
            mLastHeight = height;
            params.height = PULL_HEIGHT + height;
            requestLayout();
        }




    }


    private void drawDrag(Canvas canvas) {
        canvas.drawRect(0, 0, mWidth, PULL_HEIGHT, mBackPaint);


        mPath.reset();
        mPath.moveTo(0, PULL_HEIGHT);
        mPath.quadTo(mWidthOffset * mWidth, PULL_HEIGHT + (mHeight - PULL_HEIGHT) * 2,
                mWidth, PULL_HEIGHT);
        canvas.drawPath(mPath, mBackPaint);
    }


    private void drawSpring(Canvas canvas, int springDelta) {
        mPath.reset();
        mPath.moveTo(0, 0);
        mPath.lineTo(0, PULL_HEIGHT);
        mPath.quadTo(mWidth / 2, PULL_HEIGHT - springDelta,
                mWidth, PULL_HEIGHT);
        mPath.lineTo(mWidth, 0);
        canvas.drawPath(mPath, mBackPaint);


        int curH = PULL_HEIGHT - springDelta / 2;


        if (curH > PULL_HEIGHT - PULL_DELTA / 2) {
            int leftX = (int) (mWidth / 2 - 2 * mRadius + getSprRatio() * mRadius);
            mPath.reset();
            mPath.moveTo(leftX, curH);
            mPath.quadTo(mWidth / 2, curH - mRadius * getSprRatio() * 2,
                    mWidth - leftX, curH);
            canvas.drawPath(mPath, mBallPaint);
        } else {
            canvas.drawArc(new RectF(mWidth / 2 - mRadius, curH - mRadius, mWidth / 2 + mRadius, curH + mRadius),
                    180, 180, true, mBallPaint);
        }


    }


    private void drawPopBall(Canvas canvas) {
        mPath.reset();
        mPath.moveTo(0, 0);
        mPath.lineTo(0, PULL_HEIGHT);
        mPath.quadTo(mWidth / 2, PULL_HEIGHT - PULL_DELTA,
                mWidth, PULL_HEIGHT);
        mPath.lineTo(mWidth, 0);
        canvas.drawPath(mPath, mBackPaint);


        int cirCentStart = PULL_HEIGHT - PULL_DELTA / 2;
        int cirCenY = (int) (cirCentStart - mRadius * 2 * getPopRatio());


        canvas.drawArc(new RectF(mWidth / 2 - mRadius, cirCenY - mRadius, mWidth / 2 + mRadius, cirCenY + mRadius),
                180, 360, true, mBallPaint);


        if (getPopRatio() < 1) {
            drawTail(canvas, cirCenY, cirCentStart + 1, getPopRatio());
        } else {
            canvas.drawCircle(mWidth / 2, cirCenY, mRadius, mBallPaint);
        }




    }


    private void drawTail(Canvas canvas, int centerY, int bottom, float fraction) {
        int bezier1w = (int) (mWidth / 2 + (mRadius * 3 / 4) * (1 - fraction));
        PointF start = new PointF(mWidth / 2 + mRadius, centerY);
        PointF bezier1 = new PointF(bezier1w, bottom);
        PointF bezier2 = new PointF(bezier1w + mRadius / 2, bottom);


        mPath.reset();
        mPath.moveTo(start.x, start.y);
        mPath.quadTo(bezier1.x, bezier1.y,
                bezier2.x, bezier2.y);
        mPath.lineTo(mWidth - bezier2.x, bezier2.y);
        mPath.quadTo(mWidth - bezier1.x, bezier1.y,
                mWidth - start.x, start.y);
        canvas.drawPath(mPath, mBallPaint);
    }


    private void drawOutCir(Canvas canvas) {
        mPath.reset();
        mPath.moveTo(0, 0);
        mPath.lineTo(0, PULL_HEIGHT);
        mPath.quadTo(mWidth / 2, PULL_HEIGHT - (1 - getOutRatio()) * PULL_DELTA,
                mWidth, PULL_HEIGHT);
        mPath.lineTo(mWidth, 0);
        canvas.drawPath(mPath, mBackPaint);
        int innerY = PULL_HEIGHT - PULL_DELTA / 2 - mRadius * 2;
        canvas.drawCircle(mWidth / 2, innerY, mRadius, mBallPaint);
    }


    private int mRefreshStart = 90;
    private int mRefreshStop = 90;
    private int TARGET_DEGREE = 270;
    private boolean mIsStart = true;
    private boolean mIsRefreshing = true;


    private void drawRefreshing(Canvas canvas) {
        canvas.drawRect(0, 0, mWidth, mHeight, mBackPaint);
        int innerY = PULL_HEIGHT - PULL_DELTA / 2 - mRadius * 2;
        canvas.drawCircle(mWidth / 2, innerY, mRadius, mBallPaint);
        int outerR = mRadius + 10;


        mRefreshStart += mIsStart ? 3 : 10;
        mRefreshStop += mIsStart ? 10 : 3;
        mRefreshStart = mRefreshStart % 360;
        mRefreshStop = mRefreshStop % 360;


        int swipe = mRefreshStop - mRefreshStart;
        swipe = swipe < 0 ? swipe + 360 : swipe;


        canvas.drawArc(new RectF(mWidth / 2 - outerR, innerY - outerR, mWidth / 2 + outerR, innerY + outerR),
                mRefreshStart, swipe, false, mOutPaint);
        if (swipe >= TARGET_DEGREE) {
            mIsStart = false;
        } else if (swipe <= 10) {
            mIsStart = true;
        }
        if (!mIsRefreshing) {
            applyDone();


        }


    }


    // stop refreshing
    public void setRefreshing(boolean isFresh) {
        mIsRefreshing = isFresh;
    }


    private void drawDone(Canvas canvas) {




        int beforeColor = mOutPaint.getColor();
        if (getDoneRatio() < 0.3) {
            canvas.drawRect(0, 0, mWidth, mHeight, mBackPaint);
            int innerY = PULL_HEIGHT - PULL_DELTA / 2 - mRadius * 2;
            canvas.drawCircle(mWidth / 2, innerY, mRadius, mBallPaint);
            int outerR = (int) (mRadius + 10 + 10 * getDoneRatio() / 0.3f);
            int afterColor = Color.argb((int) (0xff * (1 - getDoneRatio() / 0.3f)), Color.red(beforeColor),
                    Color.green(beforeColor), Color.blue(beforeColor));
            mOutPaint.setColor(afterColor);
            canvas.drawArc(new RectF(mWidth / 2 - outerR, innerY - outerR, mWidth / 2 + outerR, innerY + outerR),
                    0, 360, false, mOutPaint);
        }
        mOutPaint.setColor(beforeColor);




        if (getDoneRatio() >= 0.3 && getDoneRatio() < 0.7) {
            canvas.drawRect(0, 0, mWidth, mHeight, mBackPaint);
            float fraction = (getDoneRatio() - 0.3f) / 0.4f;
            int startCentY = PULL_HEIGHT - PULL_DELTA / 2 - mRadius * 2;
            int curCentY = (int) (startCentY + (PULL_DELTA / 2 + mRadius * 2) * fraction);
            canvas.drawCircle(mWidth / 2, curCentY, mRadius, mBallPaint);
            if (curCentY >= PULL_HEIGHT - mRadius * 2) {
                drawTail(canvas, curCentY, PULL_HEIGHT, (1 - fraction));
            }
        }


        if (getDoneRatio() >= 0.7 && getDoneRatio() <= 1) {
            float fraction = (getDoneRatio() - 0.7f) / 0.3f;
            canvas.drawRect(0, 0, mWidth, mHeight, mBackPaint);
            int leftX = (int) (mWidth / 2 - mRadius - 2 * mRadius * fraction);
            mPath.reset();
            mPath.moveTo(leftX, PULL_HEIGHT);
            mPath.quadTo(mWidth / 2, PULL_HEIGHT - (mRadius * (1 - fraction)),
                    mWidth - leftX, PULL_HEIGHT);
            canvas.drawPath(mPath, mBallPaint);
        }


    }


    private int mLastHeight;


    private int getRelHeight() {
        return (int) (mSpriDeta * (1 - getRelRatio()));
    }


    private int getSpringDelta() {
        return (int) (PULL_DELTA * getSprRatio());
    }




    private static long REL_DRAG_DUR = 200;


    private long mStart;
    private long mStop;
    private int mSpriDeta;


    public void releaseDrag() {
        mStart = System.currentTimeMillis();
        mStop = mStart + REL_DRAG_DUR;
        mAniStatus = AnimatorStatus.REL_DRAG;
        mSpriDeta = mHeight - PULL_HEIGHT;
        requestLayout();
    }


    private float getRelRatio() {
        if (System.currentTimeMillis() >= mStop) {
            springUp();
            return 1;
        }
        float ratio = (System.currentTimeMillis() - mStart) / (float) REL_DRAG_DUR;
        return Math.min(ratio, 1);
    }


    private static long SPRING_DUR = 200;
    private long mSprStart;
    private long mSprStop;




    private void springUp() {
        mSprStart = System.currentTimeMillis();
        mSprStop = mSprStart + SPRING_DUR;
        mAniStatus = AnimatorStatus.SPRING_UP;
        invalidate();
    }




    private float getSprRatio() {
        if (System.currentTimeMillis() >= mSprStop) {
            popBall();
            return 1;
        }
        float ratio = (System.currentTimeMillis() - mSprStart) / (float) SPRING_DUR;
        return Math.min(1, ratio);
    }


    private static final long POP_BALL_DUR = 300;
    private long mPopStart;
    private long mPopStop;


    private void popBall() {
        mPopStart = System.currentTimeMillis();
        mPopStop = mPopStart + POP_BALL_DUR;
        mAniStatus = AnimatorStatus.POP_BALL;
        invalidate();
    }


    private float getPopRatio() {
        if (System.currentTimeMillis() >= mPopStop) {
            startOutCir();
            return 1;
        }


        float ratio = (System.currentTimeMillis() - mPopStart) / (float) POP_BALL_DUR;
        return Math.min(ratio, 1);
    }


    private static final long OUTER_DUR = 200;
    private long mOutStart;
    private long mOutStop;


    private void startOutCir() {
        mOutStart = System.currentTimeMillis();
        mOutStop = mOutStart + OUTER_DUR;
        mAniStatus = AnimatorStatus.OUTER_CIR;
        mRefreshStart = 90;
        mRefreshStop = 90;
        TARGET_DEGREE = 270;
        mIsStart = true;
        mIsRefreshing = true;
        invalidate();
    }


    private float getOutRatio() {
        if (System.currentTimeMillis() >= mOutStop) {
            mAniStatus = AnimatorStatus.REFRESHING;
            mIsRefreshing = true;
            return 1;
        }
        float ratio = (System.currentTimeMillis() - mOutStart) / (float) OUTER_DUR;
        return Math.min(ratio, 1);
    }


    private static final long DONE_DUR = 1000;
    private long mDoneStart;
    private long mDoneStop;


    private void applyDone() {
        mDoneStart = System.currentTimeMillis();
        mDoneStop = mDoneStart + DONE_DUR;
        mAniStatus = AnimatorStatus.DONE;
    }


    private float getDoneRatio() {
        if (System.currentTimeMillis() >= mDoneStop) {
            mAniStatus = AnimatorStatus.STOP;
            if (onViewAniDone != null) {
                onViewAniDone.viewAniDone();
            }
            return 1;
        }


        float ratio = (System.currentTimeMillis() - mDoneStart) / (float) DONE_DUR;
        return Math.min(ratio, 1);
    }




    private OnViewAniDone onViewAniDone;


    public void setOnViewAniDone(OnViewAniDone onViewAniDone) {
        this.onViewAniDone = onViewAniDone;
    }


    interface OnViewAniDone {
        void viewAniDone();
    }




    public void setAniBackColor(int color) {
        mBackPaint.setColor(color);
    }


    public void setAniForeColor(int color) {
        mBallPaint.setColor(color);
        mOutPaint.setColor(color);
        setBackgroundColor(color);
    }


    // the height of view is smallTimes times of circle radius
    public void setRadius(int smallTimes) {
        mRadius = mHeight / smallTimes;
    }

}


适用于各种布局的刷新,需看你的需求修改了

下面是布局的调用:

<com.tuesda.walker.circlerefresh.CircleRefreshLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:AniBackColor="#ff0097cd" >


        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffffff" >
        </ListView>
    </com.tuesda.walker.circlerefresh.CircleRefreshLayout>


方法的使用:

mRefreshLayout = (CircleRefreshLayout) findViewById(R.id.refresh_layout);
// 设置自动停止
mRefreshLayout.setOnRefreshListener(new CircleRefreshLayout.OnCircleRefreshListener() {
 @Override
 public void refreshing() {
 mRefreshLayout.postDelayed(new Runnable() {


  @Override
    public void run() {
       // 更新数据
       // 更新完后调用该方法结束刷新
    mRefreshLayout.finishRefreshing();
   }
   }, 5000);
}

@Override
public void completeRefresh() {
}
});

这种刷新效果因人而异,有需要可以放到你的项目中去,感觉挺好的。如不需要的话可以收藏,以防止下次要用,而找不到了

有需要的朋友可以 下载源码

demo 有eclipse和studio 两种。根据你的需求自己决定用哪个吧!

希望你能学到更多东西!转载请注明出处哦!


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关频道:

用户评论