Android自定义加载动画-感染体

移动开发 AndroidZLoading
Zyao89 2017年4月6日星期四 00:56

Android自定义动画系列七,今天来分享第七个自定义Loaidng动画(InfectionBallBuilder),看上去感觉有种病毒源被感染的感觉,所以名字就叫感染体,这个动画做出来的效果,我不怎么满意,但是实现方式还是可以介绍介绍的。效果图如下:

GIF有点大,手机流量请三思。

# 效果图

演示效果动画

# 介绍

首先依旧是声明,我做这些动画的初衷是为了学习和分享,所以希望大家可以指点错误,让我更好的进步。(系列加载动画的截止时间:我放弃的时候)。

最近清明放假,我也给我自己放了一个假,放松之余,玩了几天几夜的 王者荣耀 。 五黑上分的感觉--爽歪歪呀。假期的最后一天了,收收心,继续来一波动画。

上一个动画链接:Android自定义加载动画-颤抖吧!球球

言归正传,开始新的动画。

# 正文

这里先把之前一个动画进行了简单的重构,然后提取了一个基类 BaseBallBuilder ,包含了画笔的初始化,贝塞尔曲线画圆方法,以及圆点内部类。具体的实现方法可以见上一个动画,或者前往Github上进行查看,这里就不做具体说明了。

abstract class BaseBallBuilder extends ZLoadingBuilder
{
    //贝塞尔曲线常量
    private static final float                   PROP_VALUE  = 0.551915024494f;
    //小球点集合
    protected final      LinkedList<CirclePoint> mBallPoints = new LinkedList<>();
    //画笔
    protected Paint mPaint;

    /**
     * 初始化画笔
     */
    protected void initPaint(float lineWidth)
    {
      ...
    }

    /**
     * p10    p9      p8
     * ------  ------
     * p11                     p7
     * |                       |
     * |                       |
     * p0 |      (0,0)         | p6
     * |                       |
     * |                       |
     * p1                      p5
     * ------  ------
     * p2      p3      p4
     */
    protected final void initPoints(float ballR)
    {
     ...
    }

    protected final void drawBall(Canvas canvas, Path path, Paint paint)
    {
        ...
    }

    /**
     * 圆点内部类
     */
    static class CirclePoint
    {
       ...
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

这里开始今天的正题了 InfectionBallBuilder ,部分源码如下,具体步骤介绍就都写在注释里面了。很多方式都和前面的动画介绍类似,大家可以往前翻看。因为动画简单所以我这里就偷个懒,不再一一分析了。

public class InfectionBallBuilder extends BaseBallBuilder
{
    //动画间隔时间
    private static final long DURATION_TIME   = 888;
    private static final long DURATION_TIME_1 = 222;
    private static final long DURATION_TIME_2 = 333;
    private static final long DURATION_TIME_3 = 1333;
    private static final long DURATION_TIME_4 = 1333;
    //最终阶段
    private static final int  FINAL_STATE     = 4;
    private static final int  SUM_POINT_POS   = 3;
    private float mBallR;
    private Path  mPath;
    //当前动画阶段
    private int mCurrAnimatorState = 0;
    //每个小球的偏移量
    private float mCanvasTranslateOffset;

    @Override
    protected void initParams(Context context)
    {
        mBallR = getAllSize() / SUM_POINT_POS;
        mCanvasTranslateOffset = getIntrinsicWidth() / SUM_POINT_POS;
        mPath = new Path();
        initPaint(5);
        initPoints(mBallR);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        drawBall(canvas);
    }

    /**
     * 绘制小球
     *
     * @param canvas
     */
    private void drawBall(Canvas canvas)
    {
        canvas.save();
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.translate(0, -mCanvasTranslateOffset);
        super.drawBall(canvas, mPath, mPaint);
        canvas.restore();
    }

    @Override
    protected void computeUpdateValue(ValueAnimator animation, @FloatRange(from = 0.0, to = 1.0) float animatedValue)
    {
        float offset = mCanvasTranslateOffset;
        switch (mCurrAnimatorState)//这里分阶段对每个圆点进行偏移量设置
        {
            case 0:
                animation.setDuration(DURATION_TIME);
                animation.setInterpolator(new AccelerateInterpolator());
                mBallPoints.get(2).setOffsetY(animatedValue * offset);
                mBallPoints.get(3).setOffsetY(animatedValue * offset);
                mBallPoints.get(4).setOffsetY(animatedValue * offset);
                break;
            case 1:
                animation.setDuration(DURATION_TIME_1);
                animation.setInterpolator(new LinearInterpolator());
                mBallPoints.get(5).setOffsetY(animatedValue * offset);
                mBallPoints.get(6).setOffsetY(animatedValue * offset);
                mBallPoints.get(7).setOffsetY(animatedValue * offset);
                mBallPoints.get(1).setOffsetY(animatedValue * offset);
                mBallPoints.get(0).setOffsetY(animatedValue * offset);
                mBallPoints.get(11).setOffsetY(animatedValue * offset);
                break;
            case 2:
                animation.setDuration(DURATION_TIME_2);
                animation.setInterpolator(new AccelerateInterpolator());
                for (int i = 0; i < mBallPoints.size(); i++)
                {
                    if (i > 10 || i < 8)
                    {
                        mBallPoints.get(i).setOffsetY(animatedValue * offset + offset);
                    }
                    else
                    {
                        mBallPoints.get(i).setOffsetY(animatedValue * offset);
                    }
                }
                break;
            case 3:
                animation.setDuration(DURATION_TIME_3);
                animation.setInterpolator(new DecelerateInterpolator());

                mBallPoints.get(8).setOffsetY(animatedValue * offset + offset);
                mBallPoints.get(9).setOffsetY(animatedValue * offset + offset);
                mBallPoints.get(10).setOffsetY(animatedValue * offset + offset);


                mBallPoints.get(5).setOffsetX(animatedValue * offset);
                mBallPoints.get(6).setOffsetX(animatedValue * offset);
                mBallPoints.get(7).setOffsetX(animatedValue * offset);
                mBallPoints.get(1).setOffsetX(-animatedValue * offset);
                mBallPoints.get(0).setOffsetX(-animatedValue * offset);
                mBallPoints.get(11).setOffsetX(-animatedValue * offset);
                break;
            case 4:
                animation.setDuration(DURATION_TIME_4);
                mPaint.setAlpha((int) ((1 - animatedValue) * 255));
                break;
        }
    }

    @Override
    public void onAnimationRepeat(Animator animation)
    {
        if (++mCurrAnimatorState > FINAL_STATE)
        {//还原到第一阶段
            mCurrAnimatorState = 0;
            for (CirclePoint point : mBallPoints)
            {
                point.setOffsetY(0);
                point.setOffsetX(0);
            }
            mPaint.setAlpha(255);
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

# 总结

小伙伴们,要是想看更多细节,可以前往文章最下面的Github链接,如果大家觉得ok的话,希望能给个喜欢,最渴望的是在Github上给个star。谢谢了。

如果大家有什么更好的方案,或者想要实现的加载效果,可以给我留言或者私信我,我会想办法实现出来给大家。谢谢支持。

Github:zyao89/ZCustomView

作者:Zyao89;转载请保留此行,谢谢;

个人博客:https://zyao89.cn

作者: Zyao89; 转载请保留
版权声明: 自由转载-非商用-非衍生-保持署名
上次编辑时间: 2023年11月27日星期一 11:18