Android仿小米垃圾清理成功后的显示界面

效果预览:

实现思路:

1、自定义view,首先利用canvas.drawArc不断的画圆弧,通过改变角度值达到从0到有的圆圈。

2、等角度达到一定值的时候,开始显示绘制正确完成的钩子。

3、开始绘制圆弧的时候,一并绘制周围的三角形,这个是随机生成,然后慢慢想最新靠拢。

4、整体绘制完成,显示提示文字。

实现流程:

1、画圆弧,并且不断加角度,让其最后绘制成一个圆。通过postInvalidateDelayed方法让圆弧不停的自我绘制,直到角度的值等于360°算绘制完毕。绘制完毕后,回调调用完成的接口。

    /**
     * 画圆弧
     */
    private void drawArc(Canvas canvas) {
        RectF rectF = new RectF();
        rectF.left = (getWidth() - arcWidth) / 2;
        rectF.top = (getHeight() - arcWidth) / 2;
        rectF.right = (getWidth() - arcWidth) / 2 + arcWidth;
        rectF.bottom = (getHeight() - arcWidth) / 2 + arcWidth;
        if (isDraw) {
            //未运行的的时候可以执行一次
            if (!isDrawing) {
                startBezierAnimotion();
            }

            isDrawing = true;
            canvas.drawArc(rectF, -90, arcAngle, false, mArcPaint);
            arcAngle += ARC_CREATE_ANGLE;

            if (arcAngle > 330) {
                drawRight(canvas);
            }

            postInvalidateDelayed(ARC_CREATE_TIME); //每隔一段时间开始绘制

            if (arcAngle >= 360) {
                isDraw = false;
            }

            drawTriAngle(canvas);
        } else {
            canvas.drawArc(rectF, -90, 360, false, mArcPaint);
            drawRight(canvas);
            isDrawing = false;
            if(listener != null) {
                listener.onAnimotionFinished();
            }
        }
    }

2、绘制钩子。当角度大于330°的时候,绘制钩子,钩子是根据圆弧的相对角度绘制而成的,利用path就可以做到。

    /**
     * 画正确的钩子
     *
     * @param canvas\
     */
    private void drawRight(Canvas canvas) {
        Path path = new Path();
        path.moveTo((getWidth() - arcWidth) / 2 + arcWidth / 4 + arcWidth / 16, (getHeight() - arcWidth) / 2 + arcWidth / 2);
        path.lineTo((getWidth() - arcWidth) / 2 + arcWidth / 4 + arcWidth / 8 + arcWidth / 16, (getHeight() - arcWidth) / 2 + (arcWidth / 4) * 3 - arcWidth / 8);
        path.lineTo((getWidth() - arcWidth) / 2 + arcWidth / 2 + arcWidth / 4 - arcWidth / 8 + arcWidth / 16, (getHeight() - arcWidth) / 2 + arcWidth / 4 + arcWidth / 8);
        canvas.drawPath(path, mRightPaint);
    }

3、圆弧转动的动的时候,周围生成若干个随机的三角形,这里我生成的是十个。三角形的所处的位置以及运动的轨迹由ValueAnimator动画生成。

    /**
     * 坐标点的位置,用户传递到属性动画当中
     */
    public class Point implements Serializable {
        public int x;
        public int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public Point(Point src) {
            this.x = src.x;
            this.y = src.y;
        }

        public void set(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    /**
     * 用于属性动画的回掉,根据返回的参数t来计算相关数据,t是从0~1变化。
     */
    public class BezierEvaluators implements TypeEvaluator<List<Point>> {

        private Point controllPoint;

        public BezierEvaluators(Point controllPoint) {
            this.controllPoint = controllPoint;
        }

        @Override
        public List<Point> evaluate(float t, List<Point> startValue, List<Point> endValue) {
            List<Point> list = new ArrayList<>();
            if (startValue.size() > 0 && endValue.size() > 0 && startValue.size() == endValue.size()) {
                for (int i = 0; i < startValue.size(); i++) {
                    //增加角度,让每个碎片三角形所处位置不一样
                    double sum = t + ((double) i / (double) 10);
                    if (sum >= 1) {
                        sum = sum - 1;
                    }
                    // 200 - (80 * t) 旋转越来越靠近圆
                    double x = controllPoint.x + (arcWidth / 2 + 200 - (80 * t)) * Math.cos(360 * sum * Math.PI / 180);
                    double y = controllPoint.y + (arcWidth / 2 + 200 - (80 * t)) * Math.sin(360 * sum * Math.PI / 180);
                    list.add(new Point((int) x, (int) y));
                }
            }
            return list;
        }
    }

    /**
     * 开始运动三角形
     */
    private void startBezierAnimotion() {
        if(isShowTriAngle == 1) {
            float circleX = (getWidth() - arcWidth) / 2 + arcWidth / 2;
            float circleY = (getHeight() - arcWidth) / 2 + arcWidth / 2;
            float x = ((getWidth() - arcWidth) / 2) / 2;
            Point controllPoint = new Point((int) circleX, (int) circleY);
            BezierEvaluators bezierEvaluator = new BezierEvaluators(controllPoint);
            //初始化开始坐标和结束坐标,在这里这个坐标并使用,只是为了能够得属性动画产生的变化值
            List<Point> startPoint = new ArrayList<>();
            List<Point> endPoint = new ArrayList<>();
            triAngle.clear();
            for (int i = 0; i < 10; i++) {
                startPoint.add(new Point(i, i));    //随意生成
                endPoint.add(new Point(i, i));      //随意生成

                //半径之外的范围 150 - 200之间
                double r = Math.random() * 30 + 20;
                triAngle.add((int) r);
            }
            ValueAnimator anim = ValueAnimator.ofObject(bezierEvaluator, startPoint, endPoint);
            anim.addUpdateListener(this);
            anim.setDuration(1500);
            anim.setInterpolator(new AccelerateDecelerateInterpolator());   //动画运动的速率,开始和结束慢,中间快,还有其他方式可设置。
            anim.start();
        }
    }

    /**
     * 回调过来的数据,开始更新,画三角形,这样子就形成了三角形围着圆弧转,并且越靠越近,最后消失。
     */
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        List<Point> valuePoints = (List<Point>) animation.getAnimatedValue();
        this.valuePoints = valuePoints;
        invalidate();
    }

4、动画执行完毕之后,通知接口已完成。

 canvas.drawArc(rectF, -90, 360, false, mArcPaint);
            drawRight(canvas);
            isDrawing = false;
            if(listener != null) {
                listener.onAnimotionFinished();
            }

到这里就结束啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金戈鐡馬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值