Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android仿愛奇藝加載動畫實例

android仿愛奇藝加載動畫實例

編輯:關於Android編程

本篇文章介紹了android仿愛奇藝加載動畫實例,具體代碼如下:

效果圖:

用到的知識點:

  1. Path
  2. ValueAnimator

如果對Path和ValueAnimator還不熟悉推薦去看這幾個大神的Blog自定義view的目前講的最適合我的文章 ,自定義view的詳細教程和實踐,這個也是教程和實踐,感謝他們的付出!(希望大家可以認真看完,可以得到很多啟發)。

拆解動畫

  1. 一個圓先順時針的慢慢畫出來(圓不是一個閉合的圓)
  2. 這一步是一個組合動畫,圓慢慢的消失,同時三角形順時針旋轉

這裡的難點主要就是對坐標的計算,接下來我會詳細的說一下:

  1. 我們這裡把圓心作為 x,y軸的起點,向下方向為x軸正向,向右方向是y軸的正向。如果設置view的大小是等寬高的,這個時候就可以把圓的半徑設置成寬或者高的一半,如果不是等寬高的就要取寬或者高的最小值的一半,作為圓的半徑。
  2. 接下來就是三角形,也是確定坐標的難點,這個三角形是一個等邊三角形,我們希望,三角形旋轉的時候也是繞圓心進行旋轉。所以圓心到三角形的各個頂點的距離都是相等的,我這裡設置的是,三角形的邊長是圓的半徑。

相信這張圖拿出來了,結合正弦、余弦函數,p1,p2,p3的坐標也就出來了。

p1.x = -(int) ((radius / 2 * Math.tan(30 * Math.PI / 180)));
p1.y = -radius / 2;
p2.x = p1.x;
p2.y = radius / 2;
p3.x = (int) (radius / 2 / Math.sin(60 * Math.PI / 180));
p3.y = 0;

定義一些屬性

private static final String DEFAULT_COLOR = "#00ba9b";
private static final int DEFAULT_SIZE = 50;  //默認大小
private static final int DRAW_CIRCLE = 10001; //狀態標記 畫出圓形和三角形 執行畫出圓形的動畫
private static final int ROTATE_TRIANGLE = 10002; //狀態標記 執行旋轉三角形和收回圓形的動畫
private Context mContext;
private Paint trianglePaint;  //三角形的畫筆
private Paint circlePaint;  //圓形畫筆
private float paintStrokeWidth = 1; // 設置圓形的寬度
private long duration = 800; //執行時間
private int mWidth; //View的寬高
private int mHeight;
private Path trianglePath; //三角形的路徑
private Path circlePath;  //圓形的路徑
private Path dst; //由pathMeasure計算後的path
private Point p1, p2, p3; //三角形的三個點
private ValueAnimator animator; //屬性動畫 主要是獲取0-1的值來執行動畫
private float mAnimatorValue = 0;  //存放獲取到的0-1的值
private int mCurrentState = 0;  //當前的狀態 
private int radius = 0; //圓的半徑
private float startSegment; //圓開始畫的長度
private PathMeasure mMeasure; //測量path
private int triangleColor = -1;
private int circleColor = -1;

設置path

1.因為三角形是一直存在的,就先畫三角,用path來畫,我們已經知道三角形的三個頂點的坐標了,畫三角形就變得很容易了。

trianglePath = new Path();
p1 = new Point();
p2 = new Point();
p3 = new Point();
trianglePath.moveTo(p1.x, p1.y);
trianglePath.lineTo(p2.x, p2.y);
trianglePath.lineTo(p3.x, p3.y);
trianglePath.close();

這樣三角形的path就被設置好了,只要調用 canvans.drawPath() 就可以把三角形畫到畫布上。

2.然後就是畫圓,前面說過圓是有一個缺口的,我們這裡也把圓添加到path裡面,之所以沒有直接畫到canvas上面,是因為後面我們還要對圓的周長進行計算,這些操作path會幫我們操作,

circlePath = new Path();
RectF circleRect = new RectF(-radius, -radius, radius, radius);
circlePath.addArc(circleRect, 268, 358); // 這個是從圓的268°開始畫,畫258°空出兩度的一個缺口

設置屬性動畫

由於動畫需要一組0-1的數據
這裡我們借用屬性動畫提供給我們的數值來實現動畫。

private void initAnimation() {
    TimeInterpolator timeInterpolator = new AccelerateDecelerateInterpolator();
    animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
    animator.setInterpolator(timeInterpolator);
    animator.setRepeatMode(ValueAnimator.RESTART);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        mAnimatorValue = (float) animation.getAnimatedValue(); //這裡我們將會拿到一個0-1的值
        invalidate(); // 這裡進行重繪
      }
    });
    animator.addListener(new Animator.AnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
      }

      @Override
      public void onAnimationEnd(Animator animation) {

      }

      @Override
      public void onAnimationCancel(Animator animation) {
      }

      @Override
      public void onAnimationRepeat(Animator animation) { 
       //這裡進行狀態轉換,執行不同的動畫
        switch (mCurrentState) {
          case DRAW_CIRCLE:
            mCurrentState = ROTATE_TRIANGLE;
            break;
          case ROTATE_TRIANGLE:
            mCurrentState = DRAW_CIRCLE;
            break;
          default:
            break;
        }
      }
    });
  }

onDraw

分析onDraw方法

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //將原點移動到中心位置
    canvas.translate(mWidth / 2, mHeight / 2);
    // 重置path dst
    dst.reset();
    //判斷當前的狀態
    switch (mCurrentState) {
     //這裡就是我們說的第一種狀態
      case DRAW_CIRCLE:
      //這一行是獲取需要截取的path(dst)的開始位置,我們仔細觀察動畫可以看出,圓的開始是由一個位置向
      //兩端去畫的,這個位置大約是圓的1/5,當畫到了圓的起點的時候就從圓的起點開始繪制,我把執行這個動畫
      //的時間大致的設置為0-1 的0.3的位置左右。
        startSegment = (float) (mMeasure.getLength() / 5 * ((0.3 - mAnimatorValue) > 0 ? (0.3 - mAnimatorValue) : 0));
        //這裡沒什麼就是繪制三角形
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawPath(trianglePath, trianglePaint);
        //這個方法就是獲取你要截取的片段,第一個參數是開始的位置,第二個參數是結束的位置,第三個參
        //數是截取後的path,添加到path(dst),注意是添加不是替換所以前面要reset,第四個參數是,是
        //否要移動起點到當前路徑的起點保持dst中的路徑不變(舉個例子,如果dst中之前是有path的,這裡
        //設置了false,此時就會保證dst的連續性而移動dst後加入的路徑的起點到上一個路徑的終點,從而保持連續性)
        mMeasure.getSegment(startSegment, mMeasure.getLength() * mAnimatorValue, dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
         //第二種動畫
      case ROTATE_TRIANGLE:
      //對畫布進行保存,因為要執行兩個動畫,保存初始狀態下的畫布
        canvas.save();
        //然後先執行三角形的旋轉
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.rotate(360 * mAnimatorValue);
        canvas.drawPath(trianglePath, trianglePaint);
        //恢復畫布
        canvas.restore();
        //然後是外面圓的消失,消失其實和畫圓的道理是一樣的,這裡我們有一組0-1的變化的值,我們只需要
        //截取片段的時候讓起點不斷的向總長度靠近,就會出現消失的效果
        mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst, true);
        canvas.drawPath(dst, circlePaint);
        break;
      default:
        break;
    }

  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved