android仿愛奇藝加載動畫實例
本篇文章介紹了android仿愛奇藝加載動畫實例,具體代碼如下:
效果圖:
用到的知識點:
- Path
- ValueAnimator
如果對Path和ValueAnimator還不熟悉推薦去看這幾個大神的Blog自定義view的目前講的最適合我的文章 ,自定義view的詳細教程和實踐,這個也是教程和實踐,感謝他們的付出!(希望大家可以認真看完,可以得到很多啟發(fā))。
拆解動畫
- 一個圓先順時針的慢慢畫出來(圓不是一個閉合的圓)
- 這一步是一個組合動畫,圓慢慢的消失,同時三角形順時針旋轉(zhuǎn)
這里的難點主要就是對坐標的計算,接下來我會詳細的說一下:
- 我們這里把圓心作為 x,y軸的起點,向下方向為x軸正向,向右方向是y軸的正向。如果設(shè)置view的大小是等寬高的,這個時候就可以把圓的半徑設(shè)置成寬或者高的一半,如果不是等寬高的就要取寬或者高的最小值的一半,作為圓的半徑。
- 接下來就是三角形,也是確定坐標的難點,這個三角形是一個等邊三角形,我們希望,三角形旋轉(zhuǎn)的時候也是繞圓心進行旋轉(zhuǎn)。所以圓心到三角形的各個頂點的距離都是相等的,我這里設(shè)置的是,三角形的邊長是圓的半徑。
相信這張圖拿出來了,結(jié)合正弦、余弦函數(shù),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; //狀態(tài)標記 畫出圓形和三角形 執(zhí)行畫出圓形的動畫 private static final int ROTATE_TRIANGLE = 10002; //狀態(tài)標記 執(zhí)行旋轉(zhuǎn)三角形和收回圓形的動畫 private Context mContext; private Paint trianglePaint; //三角形的畫筆 private Paint circlePaint; //圓形畫筆 private float paintStrokeWidth = 1; // 設(shè)置圓形的寬度 private long duration = 800; //執(zhí)行時間 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的值來執(zhí)行動畫 private float mAnimatorValue = 0; //存放獲取到的0-1的值 private int mCurrentState = 0; //當前的狀態(tài) private int radius = 0; //圓的半徑 private float startSegment; //圓開始畫的長度 private PathMeasure mMeasure; //測量path private int triangleColor = -1; private int circleColor = -1;
設(shè)置path
1.因為三角形是一直存在的,就先畫三角,用path來畫,我們已經(jīng)知道三角形的三個頂點的坐標了,畫三角形就變得很容易了。
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就被設(shè)置好了,只要調(diào)用 canvans.drawPath() 就可以把三角形畫到畫布上。
2.然后就是畫圓,前面說過圓是有一個缺口的,我們這里也把圓添加到path里面,之所以沒有直接畫到canvas上面,是因為后面我們還要對圓的周長進行計算,這些操作path會幫我們操作,
circlePath = new Path(); RectF circleRect = new RectF(-radius, -radius, radius, radius); circlePath.addArc(circleRect, 268, 358); // 這個是從圓的268°開始畫,畫258°空出兩度的一個缺口
設(shè)置屬性動畫
由于動畫需要一組0-1的數(shù)據(jù)
這里我們借用屬性動畫提供給我們的數(shù)值來實現(xiàn)動畫。
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) { //這里進行狀態(tài)轉(zhuǎn)換,執(zhí)行不同的動畫 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(); //判斷當前的狀態(tài) switch (mCurrentState) { //這里就是我們說的第一種狀態(tài) case DRAW_CIRCLE: //這一行是獲取需要截取的path(dst)的開始位置,我們仔細觀察動畫可以看出,圓的開始是由一個位置向 //兩端去畫的,這個位置大約是圓的1/5,當畫到了圓的起點的時候就從圓的起點開始繪制,我把執(zhí)行這個動畫 //的時間大致的設(shè)置為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); //這個方法就是獲取你要截取的片段,第一個參數(shù)是開始的位置,第二個參數(shù)是結(jié)束的位置,第三個參 //數(shù)是截取后的path,添加到path(dst),注意是添加不是替換所以前面要reset,第四個參數(shù)是,是 //否要移動起點到當前路徑的起點保持dst中的路徑不變(舉個例子,如果dst中之前是有path的,這里 //設(shè)置了false,此時就會保證dst的連續(xù)性而移動dst后加入的路徑的起點到上一個路徑的終點,從而保持連續(xù)性) mMeasure.getSegment(startSegment, mMeasure.getLength() * mAnimatorValue, dst, true); canvas.drawPath(dst, circlePaint); break; //第二種動畫 case ROTATE_TRIANGLE: //對畫布進行保存,因為要執(zhí)行兩個動畫,保存初始狀態(tài)下的畫布 canvas.save(); //然后先執(zhí)行三角形的旋轉(zhuǎn) trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.rotate(360 * mAnimatorValue); canvas.drawPath(trianglePath, trianglePaint); //恢復畫布 canvas.restore(); //然后是外面圓的消失,消失其實和畫圓的道理是一樣的,這里我們有一組0-1的變化的值,我們只需要 //截取片段的時候讓起點不斷的向總長度靠近,就會出現(xiàn)消失的效果 mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst, true); canvas.drawPath(dst, circlePaint); break; default: break; } }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android實現(xiàn)仿慕課網(wǎng)下拉加載動畫
- Android使用glide加載gif動畫設(shè)置播放次數(shù)
- Android自定義加載控件實現(xiàn)數(shù)據(jù)加載動畫
- Android自定義加載loading view動畫組件
- Android Glide圖片加載(加載監(jiān)聽、加載動畫)
- Android加載Gif動畫實現(xiàn)代碼
- Android自定義view實現(xiàn)阻尼效果的加載動畫
- Android仿支付寶笑臉刷新加載動畫的實現(xiàn)代碼
- Android帶數(shù)字或紅點的底部導航攔和聯(lián)網(wǎng)等待加載動畫示例
- Android之仿美團加載數(shù)據(jù)幀動畫
相關(guān)文章
Flutter UI如何使用Provide實現(xiàn)主題切換詳解
這篇文章主要給大家介紹了關(guān)于Flutter UI如何使用Provide實現(xiàn)主題切換的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Flutter具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-04-04Android TextView漸變顏色和方向及動畫效果的設(shè)置詳解
TextView的在安卓中可以理解為一個文本視圖控件,Android的視圖控件的基類是View類,可以理解的TextView是View的子類。我們通常在.XML布局文件中會為文本視圖控件指定各種屬性來設(shè)置它的樣式,今天我們要講的當然不是傳統(tǒng)常見的那種,將會帶有漸變顏色和方向及動畫效果2021-11-11Android Usb設(shè)備的監(jiān)聽(Dev)外設(shè)端口的判定以及耳機的插拔
今天小編就為大家分享一篇關(guān)于Android Usb設(shè)備的監(jiān)聽(Dev)外設(shè)端口的判定以及耳機的插拔,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12Flutter框架實現(xiàn)Android拖動到垃圾桶刪除效果
這篇文章主要介紹了Flutter框架實現(xiàn)Android拖動到垃圾桶刪除效果,Flutter框架中的Draggable部件,用于支持用戶通過手勢拖動,它是基于手勢的一種方式,可以使用戶可以在屏幕上拖動指定的部件,下面我們來詳細了解一下2023-12-12Ubuntu中為Android增加硬件抽象層(HAL)模塊訪問Linux內(nèi)核驅(qū)動程序
本文主要介紹在Ubuntu上為Android HAL模塊訪問Linux內(nèi)核驅(qū)動程序,這里給大家提供方法和一個小的測試程序代碼,以及常遇到的問題和解決方法,有需要的小伙伴可以參考下2016-08-08解決android6.0以上不能讀取外部存儲權(quán)限的問題
今天小編就為大家分享一篇解決android6.0以上不能讀取外部存儲權(quán)限的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08