android仿愛奇藝加載動(dòng)畫實(shí)例
本篇文章介紹了android仿愛奇藝加載動(dòng)畫實(shí)例,具體代碼如下:
效果圖:

用到的知識點(diǎn):
- Path
- ValueAnimator
如果對Path和ValueAnimator還不熟悉推薦去看這幾個(gè)大神的Blog自定義view的目前講的最適合我的文章 ,自定義view的詳細(xì)教程和實(shí)踐,這個(gè)也是教程和實(shí)踐,感謝他們的付出!(希望大家可以認(rèn)真看完,可以得到很多啟發(fā))。
拆解動(dòng)畫
- 一個(gè)圓先順時(shí)針的慢慢畫出來(圓不是一個(gè)閉合的圓)
- 這一步是一個(gè)組合動(dòng)畫,圓慢慢的消失,同時(shí)三角形順時(shí)針旋轉(zhuǎn)

這里的難點(diǎn)主要就是對坐標(biāo)的計(jì)算,接下來我會詳細(xì)的說一下:
- 我們這里把圓心作為 x,y軸的起點(diǎn),向下方向?yàn)閤軸正向,向右方向是y軸的正向。如果設(shè)置view的大小是等寬高的,這個(gè)時(shí)候就可以把圓的半徑設(shè)置成寬或者高的一半,如果不是等寬高的就要取寬或者高的最小值的一半,作為圓的半徑。
- 接下來就是三角形,也是確定坐標(biāo)的難點(diǎn),這個(gè)三角形是一個(gè)等邊三角形,我們希望,三角形旋轉(zhuǎn)的時(shí)候也是繞圓心進(jìn)行旋轉(zhuǎn)。所以圓心到三角形的各個(gè)頂點(diǎn)的距離都是相等的,我這里設(shè)置的是,三角形的邊長是圓的半徑。

相信這張圖拿出來了,結(jié)合正弦、余弦函數(shù),p1,p2,p3的坐標(biāo)也就出來了。
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; //默認(rèn)大小 private static final int DRAW_CIRCLE = 10001; //狀態(tài)標(biāo)記 畫出圓形和三角形 執(zhí)行畫出圓形的動(dòng)畫 private static final int ROTATE_TRIANGLE = 10002; //狀態(tài)標(biāo)記 執(zhí)行旋轉(zhuǎn)三角形和收回圓形的動(dòng)畫 private Context mContext; private Paint trianglePaint; //三角形的畫筆 private Paint circlePaint; //圓形畫筆 private float paintStrokeWidth = 1; // 設(shè)置圓形的寬度 private long duration = 800; //執(zhí)行時(shí)間 private int mWidth; //View的寬高 private int mHeight; private Path trianglePath; //三角形的路徑 private Path circlePath; //圓形的路徑 private Path dst; //由pathMeasure計(jì)算后的path private Point p1, p2, p3; //三角形的三個(gè)點(diǎn) private ValueAnimator animator; //屬性動(dòng)畫 主要是獲取0-1的值來執(zhí)行動(dòng)畫 private float mAnimatorValue = 0; //存放獲取到的0-1的值 private int mCurrentState = 0; //當(dāng)前的狀態(tài) private int radius = 0; //圓的半徑 private float startSegment; //圓開始畫的長度 private PathMeasure mMeasure; //測量path private int triangleColor = -1; private int circleColor = -1;
設(shè)置path
1.因?yàn)槿切问且恢贝嬖诘模拖犬嬋?,用path來畫,我們已經(jīng)知道三角形的三個(gè)頂點(diǎn)的坐標(biāo)了,畫三角形就變得很容易了。
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.然后就是畫圓,前面說過圓是有一個(gè)缺口的,我們這里也把圓添加到path里面,之所以沒有直接畫到canvas上面,是因?yàn)楹竺嫖覀冞€要對圓的周長進(jìn)行計(jì)算,這些操作path會幫我們操作,
circlePath = new Path(); RectF circleRect = new RectF(-radius, -radius, radius, radius); circlePath.addArc(circleRect, 268, 358); // 這個(gè)是從圓的268°開始畫,畫258°空出兩度的一個(gè)缺口
設(shè)置屬性動(dòng)畫
由于動(dòng)畫需要一組0-1的數(shù)據(jù)
這里我們借用屬性動(dòng)畫提供給我們的數(shù)值來實(shí)現(xiàn)動(dòng)畫。
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(); //這里我們將會拿到一個(gè)0-1的值
invalidate(); // 這里進(jìn)行重繪
}
});
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) {
//這里進(jìn)行狀態(tài)轉(zhuǎn)換,執(zhí)行不同的動(dòng)畫
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);
//將原點(diǎn)移動(dòng)到中心位置
canvas.translate(mWidth / 2, mHeight / 2);
// 重置path dst
dst.reset();
//判斷當(dāng)前的狀態(tài)
switch (mCurrentState) {
//這里就是我們說的第一種狀態(tài)
case DRAW_CIRCLE:
//這一行是獲取需要截取的path(dst)的開始位置,我們仔細(xì)觀察動(dòng)畫可以看出,圓的開始是由一個(gè)位置向
//兩端去畫的,這個(gè)位置大約是圓的1/5,當(dāng)畫到了圓的起點(diǎn)的時(shí)候就從圓的起點(diǎn)開始繪制,我把執(zhí)行這個(gè)動(dòng)畫
//的時(shí)間大致的設(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);
//這個(gè)方法就是獲取你要截取的片段,第一個(gè)參數(shù)是開始的位置,第二個(gè)參數(shù)是結(jié)束的位置,第三個(gè)參
//數(shù)是截取后的path,添加到path(dst),注意是添加不是替換所以前面要reset,第四個(gè)參數(shù)是,是
//否要移動(dòng)起點(diǎn)到當(dāng)前路徑的起點(diǎn)保持dst中的路徑不變(舉個(gè)例子,如果dst中之前是有path的,這里
//設(shè)置了false,此時(shí)就會保證dst的連續(xù)性而移動(dòng)dst后加入的路徑的起點(diǎn)到上一個(gè)路徑的終點(diǎn),從而保持連續(xù)性)
mMeasure.getSegment(startSegment, mMeasure.getLength() * mAnimatorValue, dst, true);
canvas.drawPath(dst, circlePaint);
break;
//第二種動(dòng)畫
case ROTATE_TRIANGLE:
//對畫布進(jìn)行保存,因?yàn)橐獔?zhí)行兩個(gè)動(dòng)畫,保存初始狀態(tài)下的畫布
canvas.save();
//然后先執(zhí)行三角形的旋轉(zhuǎn)
trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.rotate(360 * mAnimatorValue);
canvas.drawPath(trianglePath, trianglePaint);
//恢復(fù)畫布
canvas.restore();
//然后是外面圓的消失,消失其實(shí)和畫圓的道理是一樣的,這里我們有一組0-1的變化的值,我們只需要
//截取片段的時(shí)候讓起點(diǎn)不斷的向總長度靠近,就會出現(xiàn)消失的效果
mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst, true);
canvas.drawPath(dst, circlePaint);
break;
default:
break;
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)仿慕課網(wǎng)下拉加載動(dòng)畫
- Android使用glide加載gif動(dòng)畫設(shè)置播放次數(shù)
- Android自定義加載控件實(shí)現(xiàn)數(shù)據(jù)加載動(dòng)畫
- Android自定義加載loading view動(dòng)畫組件
- Android Glide圖片加載(加載監(jiān)聽、加載動(dòng)畫)
- Android加載Gif動(dòng)畫實(shí)現(xiàn)代碼
- Android自定義view實(shí)現(xiàn)阻尼效果的加載動(dòng)畫
- Android仿支付寶笑臉?biāo)⑿录虞d動(dòng)畫的實(shí)現(xiàn)代碼
- Android帶數(shù)字或紅點(diǎn)的底部導(dǎo)航攔和聯(lián)網(wǎng)等待加載動(dòng)畫示例
- Android之仿美團(tuán)加載數(shù)據(jù)幀動(dòng)畫
相關(guān)文章
Android編程實(shí)現(xiàn)為ListView創(chuàng)建上下文菜單(ContextMenu)的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)為ListView創(chuàng)建上下文菜單(ContextMenu)的方法,簡單分析了上下文菜單的功能及ListView創(chuàng)建上下文菜單(ContextMenu)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
Android第三方開源下拉框NiceSpinner使用詳解
這篇文章主要為大家詳細(xì)介紹了Android第三方開源下拉框NiceSpinner的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android開發(fā)四大組件之實(shí)現(xiàn)電話攔截和電話錄音
這篇文章給大家介紹Android開發(fā)四大組件之實(shí)現(xiàn)電話攔截和電話錄音,涉及到android四大基本組件在程序中的應(yīng)用,對android四大基本組件感興趣的朋友可以參考下本篇文章2015-10-10
Android?WebView的使用與后退鍵處理詳細(xì)討論
在android開發(fā)中我們有時(shí)候根據(jù)項(xiàng)目的需求多少會加載一些webview,加載webview,我們有時(shí)候會根據(jù)UI來自定義返回鍵,下面這篇文章主要給大家介紹了關(guān)于Android?WebView的使用與后退鍵處理的相關(guān)資料,需要的朋友可以參考下2024-04-04
Android利用Intent啟動(dòng)和關(guān)閉Activity
這篇文章主要為大家詳細(xì)介紹了Android利用Intent啟動(dòng)和關(guān)閉Activity的相關(guān)操作,感興趣的小伙伴們可以參考一下2016-06-06
Android自定義View實(shí)現(xiàn)QQ音樂中圓形旋轉(zhuǎn)碟子
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)QQ音樂中圓形旋轉(zhuǎn)碟子,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
Android打開系統(tǒng)相機(jī)并拍照的2種顯示方法
這篇文章主要介紹了Android打開系統(tǒng)相機(jī)并拍照的2種顯示方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
Kotlin創(chuàng)建一個(gè)好用的協(xié)程作用域
這篇文章主要介紹了Kotlin創(chuàng)建一個(gè)好用的協(xié)程作用域,kotlin中使用協(xié)程,是一定要跟協(xié)程作用域一起配合使用的,否則可能協(xié)程的生命周期無法被準(zhǔn)確控制,造成內(nèi)存泄漏或其他問題2022-07-07
Android編程中File文件常見存儲與讀取操作demo示例
這篇文章主要介紹了Android編程中File文件常見存儲與讀取操作,結(jié)合實(shí)例形式分析了Android針對文件的打開、讀寫及布局等相關(guān)操作技巧,需要的朋友可以參考下2017-09-09

