1. 程式人生 > >(Android自定義View)來來來,一起再擼一個Material風格loadingView。

(Android自定義View)來來來,一起再擼一個Material風格loadingView。

本文同步自博主的個人部落格wing的地方酒館
很久很久以前,擼了一款loadingview(點選這裡回顧),當時覺得還不錯,現在看看覺得好醜啊!!! 於是想再擼一個,無意間在這裡看到一個很不錯的效果,於是手癢了,就想動動手,算起來,也有很久沒有寫過View了。

效果圖

這裡寫圖片描述

哈,可能又是我自我感覺良好,覺得效果還不錯,不過沒準再過半年我又嫌棄之前的自己了 哈哈哈。

還有呢,如果你看這篇比較吃力,推薦先去看看我之前學view的時候寫的一些部落格,難度是一點一點增加的。
簡單說說自定義view的學習方式

實現思路

看到效果,首先要分析,這裡主要是什麼組成的。

首先吶,肯定要畫兩個圓圈,對吧? 不要告訴我你不會畫圓。如果不會,請看上面的連結。

private void drawCircle(Canvas canvas, float present) {
    canvas.drawCircle(mWidth / 2, mHeight / 2 -mMaxOffset, mMaxRadius, mPaint);
    canvas.drawCircle(mWidth / 2, mHeight / 2 + mMaxOffset, mMaxRadius, mPaint);
  }

這裡寫圖片描述

然後想辦法讓圈圈轉起來,怎麼轉起來呢,肯定是rotate方法了~~這裡提供一個角度引數,讓他自增,如果到360呢,就讓他等於0,然後invalidate(),就可以實現圈圈轉動的效果。


    canvas.rotate(mDegrees += 3, mWidth / 2, mHeight / 2);
    if (mDegrees == 360) {
      mDegrees = 0;
    }
    invalidate();

這裡寫圖片描述
恩。。已經轉起來了。

接下來要想辦法讓兩個小圓在轉圈的過程中靠近,再遠離,怎麼實現呢?注意上面讓小圓有間隔的mMaxOffset!我們可以根據旋轉的百分比來動態改變這個offset!
所以,要改一下drawCircle()程式碼

float present = mDegrees / 360;
    if (present < 0.5
) { mOffset = mMaxOffset * present; } else { mOffset = mMaxOffset * (1 - present); } private void drawCircle(Canvas canvas) { canvas.drawCircle(mWidth / 2, mHeight / 2 - mOffset, mMaxRadius, mPaint); canvas.drawCircle(mWidth / 2, mHeight / 2 + mOffset, mMaxRadius, mPaint); }

現在是這樣,恩..已經有點效果了。

這裡寫圖片描述

那小圈靠近的時候,粘合動畫怎麼做?還記得qq訊息點去除嗎?跟那個道理一樣!!! 就是畫一個貝塞爾的path。座標計算思路在模仿qq訊息去除效果 這裡思路是一樣的,只不過微調了輔助點座標。直接上程式碼:

 if (present <= 0.37 || present >= 0.63) drawPath(canvas, present);

 private void drawPath(Canvas canvas, float present) {
    mPath.reset();
    mPath.moveTo(mWidth / 2 - mMaxRadius, mHeight / 2 - mOffset);
    mPath.lineTo(mWidth / 2 + mMaxRadius, mHeight / 2 - mOffset);

    float supportOffset = -30;

    if (present < 0.25) { //兩個球相交
      supportOffset = 30;
    } else if (present >= 0.25 && present < 0.375f) {
      Log.e("present", present + "");
      supportOffset = -(480 * present - 150f);
    } else if (present > 0.625) {   //開始縮小

      supportOffset = (480 * present - 330f);
      if (present > 0.75) {  //兩個球開始相交
        supportOffset = 30;
      }
      //supportOffset = 30;
    }

    Log.e("wing", supportOffset + "");

    mPath.quadTo(mWidth / 2 + supportOffset, mHeight / 2, mWidth / 2 + mMaxRadius,
        mHeight / 2 + mOffset);
    mPath.lineTo(mWidth / 2 - mMaxRadius, mHeight / 2 + mOffset);
    mPath.quadTo(mWidth / 2 - supportOffset, mHeight / 2, mWidth / 2 - mMaxRadius,
        mHeight / 2 - mOffset);
    mPath.close();
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawPath(mPath, mPaint);
  }

有一點值得注意的是,輔助點偏移座標和percent的關係。以 supportOffset = -(480 * present - 150f);作為說明。這個方程式怎麼得出出來的呢。 因為我想讓百分比從0.25->0.375變化,而輔助點座標從-30->30變化,所以是一個簡單的初中數學中的線性方程。將k和b帶入 y = kx +b 即可輕易得出。

之後在根據percent控制path的顯隱,即可實現最上效果圖的效果。

如果你感興趣,可以下載原始碼研究下~~當然,如果覺得贊,點個star是對我最大的支援~