Android自定義動(dòng)畫系列七,今天來分享第七個(gè)自定義Loading動(dòng)畫(InfectionBallBuilder)笤昨,看上去感覺有種病毒源被感染的感覺,所以名字就叫感染體
,這個(gè)動(dòng)畫做出來的效果印衔,我不怎么滿意,但是實(shí)現(xiàn)方式還是可以介紹介紹的姥敛。效果圖如下:
GIF有點(diǎn)大奸焙,手機(jī)流量請(qǐng)三思。
效果圖
介紹
首先依舊是聲明,我做這些動(dòng)畫的初衷是為了學(xué)習(xí)和分享与帆,所以希望大家可以指點(diǎn)錯(cuò)誤了赌,讓我更好的進(jìn)步。(系列加載動(dòng)畫的截止時(shí)間:我放棄的時(shí)候)鲤桥。
最近清明放假揍拆,我也給我自己放了一個(gè)假,放松之余茶凳,玩了幾天幾夜的 王者榮耀
??嫂拴。 五黑上分的感覺--爽歪歪呀。假期的最后一天了贮喧,收收心筒狠,繼續(xù)來一波動(dòng)畫。
上一個(gè)動(dòng)畫鏈接:Android自定義加載動(dòng)畫-顫抖吧箱沦!球球
言歸正傳辩恼,開始新的動(dòng)畫。
正文
這里先把之前一個(gè)動(dòng)畫進(jìn)行了簡(jiǎn)單的重構(gòu)谓形,然后提取了一個(gè)基類 BaseBallBuilder
灶伊,包含了畫筆的初始化,貝塞爾曲線畫圓方法寒跳,以及圓點(diǎn)內(nèi)部類聘萨。具體的實(shí)現(xiàn)方法可以見上一個(gè)動(dòng)畫,或者前往Github上進(jìn)行查看童太,這里就不做具體說明了米辐。
abstract class BaseBallBuilder extends ZLoadingBuilder
{
//貝塞爾曲線常量
private static final float PROP_VALUE = 0.551915024494f;
//小球點(diǎn)集合
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)
{
...
}
/**
* 圓點(diǎn)內(nèi)部類
*/
static class CirclePoint
{
...
}
}
這里開始今天的正題了 InfectionBallBuilder
,部分源碼如下书释,具體步驟介紹就都寫在注釋里面了翘贮。很多方式都和前面的動(dòng)畫介紹類似,大家可以往前翻看爆惧。因?yàn)閯?dòng)畫簡(jiǎn)單所以我這里就偷個(gè)懶狸页,不再一一分析了。
public class InfectionBallBuilder extends BaseBallBuilder
{
//動(dòng)畫間隔時(shí)間
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;
//當(dāng)前動(dòng)畫階段
private int mCurrAnimatorState = 0;
//每個(gè)小球的偏移量
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)//這里分階段對(duì)每個(gè)圓點(diǎn)進(jìn)行偏移量設(shè)置
{
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);
}
}
}
總結(jié)
小伙伴們扯再,要是想看更多細(xì)節(jié)肴捉,可以前往文章最下面的Github鏈接,如果大家覺得ok的話叔收,希望能給個(gè)喜歡齿穗,最渴望的是在Github上給個(gè)star。謝謝了饺律。
如果大家有什么更好的方案窃页,或者想要實(shí)現(xiàn)的加載效果,可以給我留言或者私信我,我會(huì)想辦法實(shí)現(xiàn)出來給大家脖卖。謝謝支持乒省。
Github:zyao89/ZCustomView
作者:Zyao89;轉(zhuǎn)載請(qǐng)保留此行畦木,謝謝袖扛;
個(gè)人博客:https://zyao89.cn