Android自定義加載動畫-搜索等待

Android自定義動畫系列十,先介紹下第九個Loading動畫(TextBuilder),只是個簡單的文字動畫,不做仔細介紹了,效果如下:

系列九動畫

上一篇介紹了Android自定義加載動畫庫zLoading的使用方式,歡迎戳入!

重點:今天來分享第十個自定義Loading動畫(SearchPathBuilder),可用與對數(shù)據(jù)庫的查詢,或者對網(wǎng)絡數(shù)據(jù)的獲取搜索等操作的等待頁面,效果如下。

效果圖

系列十動畫

正文

這個動畫是運用Path和PathMeasure 來完成的,顧名思義,PathMeasure是一個用來測量Path的類,主要方法如下:

構造方法

方法名 釋義
PathMeasure() 創(chuàng)建一個空的PathMeasure
PathMeasure(Path path, boolean forceClosed) 創(chuàng)建 PathMeasure 并關聯(lián)一個指定的Path(Path需要已經(jīng)創(chuàng)建完成)。

公共方法

返回值 方法名 釋義
void setPath(Path path, boolean forceClosed) 關聯(lián)一個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

這里有三點需要注意的地方:

  1. 不論forceClosed 設置為何種狀態(tài)(true 或者 false), 都不會影響原有 Path 的狀態(tài),即 PathPathMeasure 關聯(lián)之后,之前的的 Path 不會有任何改變。
  2. forceClosed 的設置狀態(tài)可能會影響測量結果,如果 Path 未閉合但在與 PathMeasure 關聯(lián)的時候設置 forceClosed 為 true 時,測量結果可能會比 Path 實際長度稍長一點,獲取到到是該 Path 閉合時的狀態(tài)。
  3. 在使用 getSegment 時,更改 mDrawPath 的內容后可能繪制會出現(xiàn)問題,為了兼容性給 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)//狀態(tài)切換
        {
            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)
參數(shù) 作用 備注
返回值(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

總結

小伙伴們,要是想看更多細節(jié),可以前往文章最下面的Github鏈接,如果大家覺得ok的話,希望能給個喜歡,最渴望的是在Github上給個star。謝謝了。

如果大家有什么更好的方案,或者想要實現(xiàn)的加載效果,可以給我留言或者私信我,我會想辦法實現(xiàn)出來給大家。謝謝支持。

Github:zyao89/ZCustomView

作者:Zyao89;轉載請保留此行,謝謝;

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評論 25 709
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,835評論 2 45
  • 《愛不愛》 沒有問我還愛不愛你 或許是有的 比如說“我” 我時常想還愛不愛你 我想或許是愛的 又大概是不愛的 可是...
    野衣姑娘閱讀 406評論 2 4
  • 親愛的姑娘們,你們有沒有想過,有一天,你可以擁有屬于自己的可愛的寶寶,但卻不用經(jīng)歷懷胎十月的辛苦和生產(chǎn)的痛苦?你可...
    奧斯特窩頭斯基閱讀 1,288評論 4 10
  • 誰是誰生命中的誰, 最美的遇見,才是最強悍的對手, 把最重要的留藏在心,把最不經(jīng)意的回眸當成一個信仰, 從此,心有...
    夏天lzz閱讀 351評論 0 3

友情鏈接更多精彩內容