高仿小米"安全中心"中垃圾清理成功后的显示界面

前言#

工作多年,有史以来,第一次尝试在简书和github上开始分享之旅,惭愧之际。为什么选择简书,简洁,大方,得体。为什么首先选择自定义控件这个知识点,因为是我薄弱地方,所以我要重新认识,再加深理解。本人用的小米手机,所以就直接在小米手机上面寻找模仿的UI界面咯。

效果预览#

为了做这个gif动画,还是花了点心思,第一次弄。
第一步:先用手机录屏软件或者其他方式(自行搜索)先录制好mp4文件。
第二步:我用的是mac,推荐在AppStore下载VideoGIF Free这款软件制作,将mp4转成gif。

运行效果动态图

实现思路#

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();
            }

结语#

到这里,大致流程就介绍完了。有什么不足的,欢迎指出。
欢迎在下方评论和喜欢,谢谢,转载请说明出处。

欢迎在Github上Star,详细的DEMO地址在https://github.com/yangxixi88/ProcessSuccessView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • 从开始学画画起,一直都是临摹的别人画过的,因为没有基础也就不奢望能去写生了。 但很多时候很多事不是一开始就可以成功...
    雪地兔兔阅读 373评论 1 4
  • 本周金句 1、律己,就是要逼着自己跳出舒适区,寻找另一个自己。 2、律己,是为了让自己的人生多一种可能性。 3、律...
    Aries水竹昕阅读 183评论 0 1
  • 盖伦森《离经叛道》 一、从4个方面解读 (一)根据思维方式和创新风格的不同,可以将创新者分成概念型和实验型两种类型...
    mlh缪林含阅读 247评论 0 0