Android自定義動畫系列十,先介紹下第九個Loading動畫(TextBuilder),只是個簡單的文字動畫,不做仔細介紹了,效果如下:
系列九動畫
上一篇介紹了Android自定義加載動畫庫zLoading的使用方式,歡迎戳入!
重點:今天來分享第十個自定義Loading動畫(SearchPathBuilder),可用與對數據庫的查詢,或者對網絡數據的獲取搜索等操作的等待頁面,效果如下。
效果圖
系列十動畫
正文
這個動畫是運用Path和PathMeasure 來完成的,顧名思義,PathMeasure是一個用來測量Path的類,主要方法如下:
構造方法
方法名 | 釋義 |
---|---|
PathMeasure() | 創建一個空的PathMeasure |
PathMeasure(Path path, boolean forceClosed) | 創建 PathMeasure 并關聯一個指定的Path(Path需要已經創建完成)。 |
公共方法
返回值 | 方法名 | 釋義 |
---|---|---|
void | setPath(Path path, boolean forceClosed) | 關聯一個Path |
boolean | isClosed() | 是否閉合 |
float | getLength() | 獲取Path的長度 |
boolean | nextContour() | 跳轉到下一個輪廓 |
boolean | getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) | 截取片段 |
boolean | getPosTan(float distance, float[] pos, float[] tan) | 獲取指定長度的位置坐標及該點切線值 |
boolean | getMatrix(float distance, Matrix matrix, int flags) | 獲取指定長度的位置坐標及該點Matrix |
這里有三點需要注意的地方:
- 不論
forceClosed
設置為何種狀態(true 或者 false), 都不會影響原有Path
的狀態,即Path
與PathMeasure
關聯之后,之前的的 Path 不會有任何改變。 -
forceClosed
的設置狀態可能會影響測量結果,如果 Path 未閉合但在與PathMeasure
關聯的時候設置forceClosed
為 true 時,測量結果可能會比 Path 實際長度稍長一點,獲取到到是該 Path 閉合時的狀態。 - 在使用
getSegment
時,更改mDrawPath
的內容后可能繪制會出現問題,為了兼容性給mDrawPath
添加一個單個操作,例如:mDrawPath.lineTo(0, 0);
簡單的方法介紹到這里,注釋在代碼里,下面看下代碼:
//初始化畫筆
private void initPaint()
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(15);
mPaint.setColor(Color.BLACK);
mPaint.setDither(true);
mPaint.setFilterBitmap(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
//初始化
private void initPathMeasure()
{
mDrawPath = new Path();//最終繪制的路徑
mPathMeasure = new PathMeasure();
}
//初始化路徑
private void initPaths()
{
float r = mR * 0.4f;//內圓半徑
mPath = new Path();//外圓路徑
mPath.addArc(new RectF(getViewCenterX() - mR, getViewCenterY() - mR, getViewCenterX() + mR, getViewCenterY() + mR), 45, 359.9f);
mPathMeasure.setPath(mPath, false);
float[] pos = new float[2];
mPathMeasure.getPosTan(0, pos, null);
mPathZoom = new Path();//內部放大鏡路徑
mPathZoom.addArc(new RectF(getViewCenterX() - r, getViewCenterY() - r, getViewCenterX() + r, getViewCenterY() + r), 45, 359.9f);
mPathZoom.lineTo(pos[0], pos[1]);
}
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawPath(mDrawPath, mPaint);
}
@Override
protected void computeUpdateValue(ValueAnimator animation, @FloatRange(from = 0.0, to = 1.0) float animatedValue)
{
switch (mCurrAnimatorState)//狀態切換
{
case 0:
case 1://第一階段
resetDrawPath();//重置
mPathMeasure.setPath(mPath, false);//綁定路徑
float stop = mPathMeasure.getLength() * animatedValue;
float start = (float) (stop - ((0.5 - Math.abs(animatedValue - 0.5)) * 200f));
mPathMeasure.getSegment(start, stop, mDrawPath, true);//截取片段
break;
case 2://第二階段
resetDrawPath();//重置
mPathMeasure.setPath(mPath, false);
stop = mPathMeasure.getLength() * animatedValue;
start = 0;
mPathMeasure.getSegment(start, stop, mDrawPath, true);
break;
case 3://第三階段
mPathMeasure.setPath(mPathZoom, false);
stop = mPathMeasure.getLength();
start = stop * (1 - animatedValue);
mPathMeasure.getSegment(start, stop, mDrawPath, true);
break;
default:
break;
}
}
@Override
public void onAnimationRepeat(Animator animation)
{
if (++mCurrAnimatorState > FINAL_STATE)
{//還原到第一階段
mCurrAnimatorState = 0;
}
}
//這里是復用重置,并且修復一個無法繪制的問題
private void resetDrawPath()
{
mDrawPath.reset();
mDrawPath.lineTo(0, 0);//不知道什么坑
}
這里解釋下getSegment,方法如下:
boolean getSegment (float startD, float stopD, Path dst, boolean startWithMoveTo)
參數 | 作用 | 備注 |
---|---|---|
返回值(boolean) | 判斷截取是否成功 | true 表示截取成功,結果存入dst中,false 截取失敗,不會改變dst中內容 |
startD | 開始截取位置距離 Path 起點的長度 | 取值范圍: 0 <= startD < stopD <= Path總長度 |
stopD | 結束截取位置距離 Path 起點的長度 | 取值范圍: 0 <= startD < stopD <= Path總長度 |
dst | 截取的 Path 將會添加到 dst 中 | 注意: 是添加,而不是替換 |
startWithMoveTo | 起始點是否使用 moveTo | 用于保證截取的 Path 第一個點位置不變 |
ZLoading庫的使用方式
ZLoading庫: Android自定義加載動畫庫zLoading
總結
小伙伴們,要是想看更多細節,可以前往文章最下面的Github鏈接,如果大家覺得ok的話,希望能給個喜歡,最渴望的是在Github上給個star。謝謝了。
如果大家有什么更好的方案,或者想要實現的加載效果,可以給我留言或者私信我,我會想辦法實現出來給大家。謝謝支持。
Github:zyao89/ZCustomView
作者:Zyao89;轉載請保留此行,謝謝;
個人博客:https://zyao89.cn