欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android仿視頻加載旋轉(zhuǎn)小球動(dòng)畫效果的實(shí)例代碼

 更新時(shí)間:2018年09月04日 16:57:07   作者:萬學(xué)冬  
這篇文章主要介紹了Android仿視頻加載旋轉(zhuǎn)小球動(dòng)畫效果的實(shí)例代碼,文中給大家提到了PathMeasure的用法,介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

先上個(gè)效果圖,以免大家跑錯(cuò)地了。   

嗯,除了只能錄三秒,其他沒啥問題。   

下面分析一下怎么實(shí)現(xiàn)上面這個(gè)效果。   

理性分析后我們可以看到是幾個(gè)小球繞著一個(gè)圓進(jìn)行運(yùn)動(dòng),那這里面的重點(diǎn)我們看看什么。   

繪制五個(gè)球,沒什么難度,讓球繞圓進(jìn)行運(yùn)動(dòng),這個(gè)好像我們沒有見到是怎么去實(shí)現(xiàn)了,那下就說這個(gè)。   

從本質(zhì)上看,球繞圓運(yùn)動(dòng),其實(shí)我們可以看作是一個(gè)物體繞指定的路勁運(yùn)動(dòng),那我們就有下面幾個(gè)東西需要說一下:

1:Path
2:ValueAnimator
3:PathMeasure  

前兩個(gè)大家應(yīng)該都見過,一個(gè)是路徑,就是可以自己繪制路線的一個(gè)工具,一個(gè)是動(dòng)畫,用來指定物體運(yùn)動(dòng)的工具,那第三個(gè)是一個(gè)關(guān)于測(cè)量路徑的類。   

下面說說PathMeasure的用法。   

首先是初始化:

pathMeasure = new PathMeasure(path, false);  

兩個(gè)參數(shù)第一個(gè),第一個(gè)就是我們需要用到的路徑,第二個(gè)參數(shù)意思就是這個(gè)以路徑頭尾是否相連來計(jì)算結(jié)果,通常我們就寫false就行,不會(huì)有問題。   

然后是用法:

private float[] mCurrentPositionOne = new float[2];
float value = (Float) 
animation.getAnimatedValue();
pathMeasure.getPosTan(value, mCurrentPositionOne, null);
  我們可以看見把一個(gè)二維數(shù)組放到了getPosTan這個(gè)方法里面,然后還有一個(gè)animation,這里的animation來自哪里呢?來自這里:valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
    // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
    float value = (Float) animation.getAnimatedValue();
    pathMeasure.getPosTan(value, mCurrentPositionOne, null);
    postInvalidate();
  }
});

看見沒,是動(dòng)畫的監(jiān)聽里面來的,getPosTan的最后一個(gè)參數(shù)通常也就寫null就行了,那么這整個(gè)一行的代碼意思就是當(dāng)動(dòng)畫發(fā)生了變化,就執(zhí)行這行代碼,然后這行代碼會(huì)把這個(gè)時(shí)間點(diǎn)的路徑上的坐標(biāo)賦值給mCurrentPositionOne。   

那我們獲取到看這個(gè)路徑上的坐標(biāo)點(diǎn)怎么辦呢?   

立馬用來ondraw里面啊,我的小球此時(shí)就可以根據(jù)這個(gè)坐標(biāo)點(diǎn)去繪制自己的位置,這個(gè)的話,當(dāng)動(dòng)畫開始時(shí),小球就會(huì)不斷接受新的坐標(biāo),然后不斷重繪,最終產(chǎn)生旋轉(zhuǎn)小球的效果。     

我先把屬性動(dòng)畫的代碼貼出來:

if (valueAnimatorOne == null) {
   valueAnimatorOne = ValueAnimator.ofFloat(0, pathMeasure.getLength());
  valueAnimatorOne.setDuration(800);
  // 減速插值器
  valueAnimatorOne.setInterpolator(new DecelerateInterpolator());
  valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
      // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
      float value = (Float) animation.getAnimatedValue();
      pathMeasure.getPosTan(value, mCurrentPositionOne, null);
      postInvalidate();
    }
  });
  valueAnimatorOne.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animator) {
      finishAnimateOne = 1;
    }
    @Override
    public void onAnimationEnd(Animator animator) {
      finishAnimateOne = 0;
    }
    @Override
    public void onAnimationCancel(Animator animator) {
    }
    @Override
    public void onAnimationRepeat(Animator animator) {
    }
  });
}
valueAnimatorOne.start();

  我寫了個(gè)800,也就是動(dòng)畫的維持時(shí)間,但是我們發(fā)現(xiàn)有啊后幾個(gè)小球,所以我們需要繪制好幾個(gè)小球,然后給他們不同的動(dòng)畫,為什么呢?因?yàn)閯?dòng)畫都一樣,小球就疊加在一起了,我們就只能看見一個(gè)球了。   

說到這里的話,我們的目標(biāo)算時(shí)完成了,具體的操作,大家參考以下代碼,或者去:android自定義View索引     

里面動(dòng)畫的demo進(jìn)行下載,大家隨意,下面給出代碼:

/**


 * 仿視頻加載動(dòng)畫,旋轉(zhuǎn)的藍(lán)色小球
 */
public class RotaryBall extends View {
  private Path rotationPath;
  private float radius;
  private Paint circlePaintOne;
  private PathMeasure pathMeasure;
  private int finishAnimateOne = 0;  // 用來判斷當(dāng)前動(dòng)畫有沒有開始
  private int finishAnimateTwo = 0;  // 用來判斷當(dāng)前動(dòng)畫有沒有開始
  private int finishAnimateThree = 0;  // 用來判斷當(dāng)前動(dòng)畫有沒有開始
  private int finishAnimateFour = 0;  // 用來判斷當(dāng)前動(dòng)畫有沒有開始
  private int finishAnimateFive = 0;  // 用來判斷當(dāng)前動(dòng)畫有沒有開始
  private Handler handler;
  private float[] mCurrentPositionOne = new float[2];
  private float[] mCurrentPositionTwo = new float[2];
  private float[] mCurrentPositionThree = new float[2];
  private float[] mCurrentPositionFour = new float[2];
  private float[] mCurrentPositionFive = new float[2];
  private ValueAnimator valueAnimatorOne = null;
  private ValueAnimator valueAnimatorTwo = null;
  private ValueAnimator valueAnimatorThree = null;
  private ValueAnimator valueAnimatorFour = null;
  private ValueAnimator valueAnimatorFive = null;
  private int currentStatus = -1;  //-1表示第一次運(yùn)行,0表示動(dòng)畫結(jié)束或者沒開始,1表示正在運(yùn)動(dòng)中
  private boolean animateOrNot = true;  //用來決定是否開啟動(dòng)畫
  public RotaryBall(Context context) {
    super(context);
    initData();
  }
  public RotaryBall(Context context, AttributeSet attrs) {
    super(context, attrs);
    initData();
  }
  private void initData() {
    rotationPath = new Path();
    circlePaintOne = new Paint();
    circlePaintOne.setColor(Color.BLUE);
    circlePaintOne.setAntiAlias(true);
    handler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
          case 4:
            if (finishAnimateOne == 0) {
              startAnimatorOne();
            }
            if (finishAnimateTwo == 0) {
              startAnimatorTwo();
            }
            if (finishAnimateThree == 0) {
              startAnimatorThree();
            }
            if (finishAnimateFour == 0) {
              startAnimatorFour();
            }
            if (finishAnimateFive == 0) {
              startAnimatorFive();
            }
            currentStatus = 0;
        }
      }
    };
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    radius = getMeasuredWidth() / 2;
  }
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
//    rotationPath.addCircle(radius, radius, radius - 10, CW);
    rotationPath.moveTo(radius, 0 + 10);
    rotationPath.cubicTo(radius, 0 + 10, radius * 2 - 10, 0 + 10, radius * 2 - 10, radius);
    rotationPath.cubicTo(radius * 2 - 10, radius, radius * 2 - 10, radius * 2 - 10, radius, radius * 2 - 10);
    rotationPath.cubicTo(radius, radius * 2 - 10, 0 + 10, radius * 2 - 10, 0 + 10, radius);
    rotationPath.cubicTo(0 + 10, radius, 0 + 10, 0 + 10, radius, 0 + 10);
    rotationPath.close();
    pathMeasure = new PathMeasure(rotationPath, false);
    //下面繪制不同半徑的小圓
    canvas.drawCircle(mCurrentPositionOne[0], mCurrentPositionOne[1], 10, circlePaintOne);
    canvas.drawCircle(mCurrentPositionTwo[0], mCurrentPositionTwo[1], 9, circlePaintOne);
    canvas.drawCircle(mCurrentPositionThree[0], mCurrentPositionThree[1], 7, circlePaintOne);
    canvas.drawCircle(mCurrentPositionFour[0], mCurrentPositionFour[1], 5, circlePaintOne);
    canvas.drawCircle(mCurrentPositionFive[0], mCurrentPositionFive[1], 3, circlePaintOne);
    if (currentStatus == -1) {
      Message message = new Message();
      message.what = 4;
      handler.sendMessage(message);
    }
    if (animateOrNot) {
      if (currentStatus == 0) {
        currentStatus = 1;
        new Thread() {      //用線程來統(tǒng)一五個(gè)圓的周期
          @Override
          public void run() {
            super.run();
            try {
              Log.d("thread", "thread");
              Thread.sleep(1600);
              Message message = new Message();
              message.what = 4;
              handler.sendMessage(message);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
        }.start();
      }
    }
  }
  //供外部調(diào)用,開始動(dòng)畫
  public void startAnimate() {
    if (!animateOrNot) {
      animateOrNot = true;
      currentStatus = -1;
      invalidate();
    }
  }
  //供外部調(diào)用,停止動(dòng)畫
  public void stopAnimate() {
    if (animateOrNot) {
      animateOrNot = false;
    }
  }
  //界面被銷毀
  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    stopAnimate();
    clearAllAnimation();
  }
  //清除所有動(dòng)畫效果
  private void clearAllAnimation() {
    if (valueAnimatorOne != null){
      if (valueAnimatorOne.isRunning()){
        valueAnimatorOne.cancel();
      }
      valueAnimatorOne.removeAllUpdateListeners();
      valueAnimatorOne = null;
    }
    if (valueAnimatorTwo != null){
      if (valueAnimatorTwo.isRunning()){
        valueAnimatorTwo.cancel();
      }
      valueAnimatorTwo.removeAllUpdateListeners();
      valueAnimatorTwo = null;
    }
    if (valueAnimatorThree != null){
      if (valueAnimatorThree.isRunning()){
        valueAnimatorThree.cancel();
      }
      valueAnimatorThree.removeAllUpdateListeners();
      valueAnimatorThree = null;
    }
    if (valueAnimatorFour != null){
      if (valueAnimatorFour.isRunning()){
        valueAnimatorFour.cancel();
      }
      valueAnimatorFour.removeAllUpdateListeners();
      valueAnimatorFour = null;
    }
    if (valueAnimatorFive != null){
      if (valueAnimatorFive.isRunning()){
        valueAnimatorFive.cancel();
      }
      valueAnimatorFive.removeAllUpdateListeners();
      valueAnimatorFive = null;
    }
  }
  //開始第一個(gè)小球的動(dòng)畫
  private void startAnimatorOne() {
    if (valueAnimatorOne == null) {
      Log.d("valueAnimatorOne", "valueAnimatorOne");
      valueAnimatorOne = ValueAnimator.ofFloat(0, pathMeasure.getLength());
      valueAnimatorOne.setDuration(800);
      // 減速插值器
      valueAnimatorOne.setInterpolator(new DecelerateInterpolator());
      valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
          float value = (Float) animation.getAnimatedValue();
          pathMeasure.getPosTan(value, mCurrentPositionOne, null);
          postInvalidate();
        }
      });
      valueAnimatorOne.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
          finishAnimateOne = 1;
        }
        @Override
        public void onAnimationEnd(Animator animator) {
          finishAnimateOne = 0;
        }
        @Override
        public void onAnimationCancel(Animator animator) {
        }
        @Override
        public void onAnimationRepeat(Animator animator) {
        }
      });
    }
    valueAnimatorOne.start();
  }
  //開始第二個(gè)小球的動(dòng)畫
  private void startAnimatorTwo() {
    if (valueAnimatorTwo == null) {
      valueAnimatorTwo = ValueAnimator.ofFloat(0, pathMeasure.getLength());
      valueAnimatorTwo.setDuration(1000);
      // 減速插值器
      valueAnimatorTwo.setInterpolator(new DecelerateInterpolator());
      valueAnimatorTwo.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          float value = (Float) animation.getAnimatedValue();
          // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
          pathMeasure.getPosTan(value, mCurrentPositionTwo, null);
          postInvalidate();
        }
      });
      valueAnimatorTwo.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
          finishAnimateTwo = 1;
        }
        @Override
        public void onAnimationEnd(Animator animator) {
          finishAnimateTwo = 0;
        }
        @Override
        public void onAnimationCancel(Animator animator) {
        }
        @Override
        public void onAnimationRepeat(Animator animator) {
        }
      });
    }
    valueAnimatorTwo.start();
  }
  //開始第三個(gè)小球的動(dòng)畫
  private void startAnimatorThree() {
    if (valueAnimatorThree == null) {
      valueAnimatorThree = ValueAnimator.ofFloat(0, pathMeasure.getLength());
      valueAnimatorThree.setDuration(1200);
      // 減速插值器
      valueAnimatorThree.setInterpolator(new DecelerateInterpolator());
      valueAnimatorThree.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          float value = (Float) animation.getAnimatedValue();
          // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
          pathMeasure.getPosTan(value, mCurrentPositionThree, null);
          postInvalidate();
        }
      });
      valueAnimatorThree.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
          finishAnimateThree = 1;
        }
        @Override
        public void onAnimationEnd(Animator animator) {
          finishAnimateThree = 0;
        }
        @Override
        public void onAnimationCancel(Animator animator) {
        }
        @Override
        public void onAnimationRepeat(Animator animator) {
        }
      });
    }
    valueAnimatorThree.start();
  }
  //開始第四個(gè)小球的動(dòng)畫
  private void startAnimatorFour() {
    if (valueAnimatorFour == null) {
      valueAnimatorFour = ValueAnimator.ofFloat(0, pathMeasure.getLength());
      valueAnimatorFour.setDuration(1400);
      // 減速插值器
      valueAnimatorFour.setInterpolator(new DecelerateInterpolator());
      valueAnimatorFour.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          float value = (Float) animation.getAnimatedValue();
          // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
          pathMeasure.getPosTan(value, mCurrentPositionFour, null);
          postInvalidate();
        }
      });
      valueAnimatorFour.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
          finishAnimateFour = 1;
        }
        @Override
        public void onAnimationEnd(Animator animator) {
          finishAnimateFour = 0;
        }
        @Override
        public void onAnimationCancel(Animator animator) {
        }
        @Override
        public void onAnimationRepeat(Animator animator) {
        }
      });
    }
    valueAnimatorFour.start();
  }
  //開始第五個(gè)小球的動(dòng)畫
  private void startAnimatorFive() {
    if (valueAnimatorFive == null) {
      valueAnimatorFive = ValueAnimator.ofFloat(0, pathMeasure.getLength());
      valueAnimatorFive.setDuration(1600);
      // 減速插值器
      valueAnimatorFive.setInterpolator(new DecelerateInterpolator());
      valueAnimatorFive.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          float value = (Float) animation.getAnimatedValue();
          // 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
          pathMeasure.getPosTan(value, mCurrentPositionFive, null);
          postInvalidate();
        }
      });
      valueAnimatorFive.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
          finishAnimateFive = 1;
        }
        @Override
        public void onAnimationEnd(Animator animator) {
          finishAnimateFive = 0;
        }
        @Override
        public void onAnimationCancel(Animator animator) {
        }
        @Override
        public void onAnimationRepeat(Animator animator) {
        }
      });
    }
    valueAnimatorFive.start();
  }
}

總結(jié)

以上所述是小編給大家介紹的Android仿視頻加載旋轉(zhuǎn)小球動(dòng)畫實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Android 開發(fā)中根據(jù)搜索內(nèi)容實(shí)現(xiàn)TextView中的文字部分加粗

    Android 開發(fā)中根據(jù)搜索內(nèi)容實(shí)現(xiàn)TextView中的文字部分加粗

    最近遇到一個(gè)需求,需要做一個(gè)搜索功能。搜索的內(nèi)容需要加粗顯示。實(shí)現(xiàn)方法很簡(jiǎn)單,下面通過本文給大家分享Android 開發(fā)中根據(jù)搜索內(nèi)容實(shí)現(xiàn)TextView中的文字部分加粗樣式,非常不錯(cuò),需要的朋友參考下
    2017-03-03
  • android連接wifi時(shí)獲取廣播地址代碼

    android連接wifi時(shí)獲取廣播地址代碼

    本文詳細(xì)介紹android連接wifi時(shí)獲取廣播地址的方法,需要了解的朋友可以參考下,獲取對(duì)你有所幫助
    2012-12-12
  • 谷歌被屏蔽后如何搭建安卓環(huán)境

    谷歌被屏蔽后如何搭建安卓環(huán)境

    從5月27日開始,谷歌(Google)在華的幾乎所有的服務(wù)都處于無法使用的狀態(tài),除了搜索引擎遭到屏蔽之外,谷歌的郵箱(Gmail)、日歷(Calendar)、翻譯(Translate)、地圖(Maps)、分析(Analytics)和Google AdSense等產(chǎn)品也受到了影響。同時(shí)安裝安卓環(huán)境的時(shí)候同樣容易出現(xiàn)問題
    2014-06-06
  • android耳機(jī)左右聲道接反具體修正方法

    android耳機(jī)左右聲道接反具體修正方法

    android 耳機(jī)左右聲道接反如何修正,具體的修改方法如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助
    2013-06-06
  • Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件方法示例

    Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件方法示例

    這篇文章主要給大家介紹了關(guān)于Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • Android實(shí)現(xiàn)可拖拽的GridView效果長(zhǎng)按可拖拽刪除數(shù)據(jù)源

    Android實(shí)現(xiàn)可拖拽的GridView效果長(zhǎng)按可拖拽刪除數(shù)據(jù)源

    這篇文章主要介紹了Android實(shí)現(xiàn)可拖拽的GridView效果長(zhǎng)按可拖拽刪除數(shù)據(jù)源,要實(shí)現(xiàn)的基本功能是長(zhǎng)按,移到垃圾桶,刪除數(shù)據(jù),需要的朋友可以參考下
    2017-12-12
  • Android ViewDragHelper完全解析 自定義ViewGroup神器

    Android ViewDragHelper完全解析 自定義ViewGroup神器

    這篇文章主要為大家詳細(xì)介紹了Android ViewDragHelper完全解析,自定義ViewGroup神器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android 幀動(dòng)畫的實(shí)例詳解

    Android 幀動(dòng)畫的實(shí)例詳解

    這篇文章主要介紹了Android 幀動(dòng)畫的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • Android 雙擊返回鍵退出程序的方法總結(jié)

    Android 雙擊返回鍵退出程序的方法總結(jié)

    這篇文章主要介紹了Android 雙擊返回鍵退出程序的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Flutter適配深色模式的方法(DarkMode)

    Flutter適配深色模式的方法(DarkMode)

    這篇文章主要介紹了Flutter適配深色模式的方法(DarkMode),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10

最新評(píng)論