Gif(2)-加载视图-波纹

先看看下面这个Gif。看起来还不错 。

突然想到,前两天实现的那个波纹,虽然有点Low,确有点异曲同工之感,这个的 一圈圈的波纹 和 变大变小的内圆 其实就是个摆设,既然不能显示进度,最后的OK感觉有点莫名其妙。

然后进行组合了一下, 大圆代表整个进度,而内心圆代表当前进度。一波波的波纹代表加载效果。完成后显示OK。

当然Gif图的 OK 还有一个放大后执行了缩小,又放大了一点点。这一块,没有整,累了,睡觉了。。无非设置textSize了。

实现如下:
加载波纹看起来颜色不是挺顺眼,奈何老夫不懂配色。

初始化

有三个状态,默认为None,根据每个状态提供一个animator。

public class LoadRippleCircleView extends BaseView {
    private int mInsideCircleRadius = DisplayUtils.dp2px(this.getContext(), 60);
    private int mOuterCircleRadius = mInsideCircleRadius + DisplayUtils.dp2px(this.getContext(), 5);
    private Status status = Status.NONE;
    private enum Status {
        NONE, Starting, Loading, ENDING

    }
    // 对应三个执行状态的 value值
    private ValueAnimator mStartingValueAnimator, mLoadingValueAnimator, mEndingValueAnimator;
    private float mStartingValue = 0.0f, mLoadingValue = 0.0f, mEndingValue = 0.0f;

    // 波纹
    private int mLoadingRadius = DisplayUtils.dp2px(this.getContext(), 5);
    private int mFirstRip = DisplayUtils.dp2px(this.getContext(), 60) / 2;
    private int mSecondRip = DisplayUtils.dp2px(this.getContext(), 60) / 4 * 3;
    private int mThirdRip = DisplayUtils.dp2px(this.getContext(), 60);

    // 将进度内圆进行分份
    private int min = 0, max = 100;
    private int currValue;

    public LoadRippleCircleView(Context context) {
        this(context, null);
    }
    public LoadRippleCircleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public LoadRippleCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mStartingValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(1000);
        mLoadingValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(700);
        mEndingValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(1000);
        initAnimatorListener();
    }

    private void initAnimatorListener() {
        mStartingValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mStartingValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        mStartingValueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                status = Status.Starting;
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                status = Status.Loading;
                mLoadingValueAnimator.start();
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        mLoadingValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mLoadingValue = (float) animation.getAnimatedValue();

                mLoadingRadius = (int) (mInsideCircleRadius * 1.0f / max * currValue);
                if (currValue >= max) {
                    animation.cancel();
                    status = Status.ENDING;
                    mEndingValueAnimator.start();
                }
                postInvalidate();
            }
        });
        mLoadingValueAnimator.setRepeatCount(-1);
        mEndingValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mEndingValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        mStartingValueAnimator.start();
    }

复制代码

测量大小


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int measuredWidth = width, measuredHeight = height;

        if (widthMode != MeasureSpec.EXACTLY) {
            measuredWidth = mOuterCircleRadius * 2 + mMargin * 2 + mPadding * 2;
        }
        if (heightMode != MeasureSpec.EXACTLY) {
            measuredHeight = mOuterCircleRadius * 2 + mMargin * 2 + mPadding * 2;
        }
        setMeasuredDimension(measuredWidth, measuredHeight);
    }
复制代码

绘制

starting:开始绘制背景圆。

loading:绘制进度圆,还有波浪。

ending:缩小进度圆后放大字体,放大背景圆(从0开始),同时绘制Path。

(缩小进度圆的速度)比(放大背景圆的速度)快(1/4),剩下的1/4时间放大Ok。

(缩小进度圆 + 放大OK) 与 (背景圆) 与 (Path绘制) 同比。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#FF31C994"));
        canvas.translate(mViewWidth / 2, mViewHeight / 2);
        canvas.save();
        if (status == Status.Starting) {
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setColor(Color.parseColor("#A1E3CB"));
            canvas.drawCircle(0, 0, mInsideCircleRadius * mStartingValue, mPaint);
        }
        if (status == Status.Loading) {
            // 底 圆
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setColor(Color.parseColor("#A1E3CB"));
            canvas.drawCircle(0, 0, mInsideCircleRadius, mPaint);
            // 波纹
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.parseColor("#ff92C5AA"));
            mPaint.setStyle(Paint.Style.STROKE);
            if (mFirstRip > mLoadingRadius + 15) // 感觉+15 更为协调些
                canvas.drawCircle(0, 0, (mLoadingRadius + (mFirstRip - mLoadingRadius)) * mLoadingValue, mPaint);
            if (mSecondRip > mLoadingRadius + 15)
                canvas.drawCircle(0, 0, (mLoadingRadius + (mSecondRip - mLoadingRadius)) * mLoadingValue, mPaint);
            if (mThirdRip > mLoadingRadius + 15)
                canvas.drawCircle(0, 0, (mLoadingRadius + (mThirdRip - mLoadingRadius)) * mLoadingValue, mPaint);
            // 进度圆
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setColor(Color.parseColor("#D2F1E6"));
            canvas.drawCircle(0, 0, mLoadingRadius, mPaint);
        }
        if (status == Status.ENDING) {
            // 底圆 由小变大
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setColor(Color.parseColor("#A1E3CB"));
            canvas.drawCircle(0, 0, mInsideCircleRadius * mEndingValue, mPaint);
            if (mEndingValue < 0.75f) {
                // 进度圆 由大变小
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                mPaint.setColor(Color.parseColor("#D2F1E6"));
                canvas.drawCircle(0, 0, mLoadingRadius * (0.75f - mEndingValue), mPaint);
            } else {
                mPaint.setColor(Color.WHITE);
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                float f = DisplayUtils.sp2px(this.getContext(), 65) / (1f - 0.75f);
                mPaint.setTextSize((mEndingValue - 0.75f) * f);
                String txt = "OK";
                Rect rect = new Rect();
                mPaint.getTextBounds(txt, 0, txt.length(), rect);
                int w = rect.width();
                int h = rect.height();
                canvas.drawText(txt, -(w / 2), (h / 2), mPaint);
            }
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(DisplayUtils.dp2px(this.getContext(), 1.5f));
            Path pathCircle = new Path();
            RectF oval = new RectF(-mOuterCircleRadius, -mOuterCircleRadius, mOuterCircleRadius, mOuterCircleRadius);
            pathCircle.addArc(oval, 270, 360f * mEndingValue);
            canvas.drawPath(pathCircle, mPaint);
        }
        canvas.restore();
    }
复制代码

对外接口

    public void setCurrValue(int currValue) {
        this.currValue = currValue;
    }
    public void setMin().....
    public void setMax()....
}
复制代码

src

转载于:https://juejin.im/post/5ae740c051882567161a59b3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值