看到支付寶的下拉重新整理有乙個笑臉的動畫,因此自己也動手實現一下。效果圖如下:
這一部分的笑臉就是乙個半圓弧,加上兩顆眼睛,這部分比較簡單,用於一開始的展示。
2.1、先是從底部有乙個圓形在運動,運動在左眼位置時把左眼給繪製,同時圓形繼續運動,運動到右眼位置時繪製右眼,圓形繼續運動到最右邊的位置。
2.2、當上面的圓形運動到最右邊時候,開始不斷繪製臉,從右向左,臉不斷增長,這裡臉設定為接近半個圓形的大小。
2.3、當臉畫完的時候,開始讓臉旋轉起來,就是一邊在增長的同時,另一邊是在縮短的。
2.4、最後臉的部分是慢慢縮為乙個點的,此時動畫結束。
2.5、時間可以看做時最底部的那個圓形運動了兩周,因此可以用分數來表示每一部分的運動,如從底部開始到左眼睛的位置,用時比例為(1/4+1/8),最終控制每一部分的動畫比例的和加起來為2即可。
大概是這樣的時間比例:(1/4+1/8) + (1/4) +(1/8) +(1/2) +(1/4) +(1/4+1/4) ,其中1/4代表1/4個圓弧,也是1/4的時間,其它的類似。
處理為wrap_content情況,那麼它的specmode是at_most模式,在這種模式下它的寬/高等於spectsize,這種情況下view的spectsize是parentsize,而parentsize是父容器目前可以使用大小,就是父容器當前剩餘的空間大小, 就相當於使用match_parent一樣 的效果,因此我們可以設定乙個預設的值。
@override
protected
void
onmeasure(int widthmeasurespec, int heightmeasurespec) else
if (widthspectmode == measurespec.at_most) else
if (heightspectmode == measurespec.at_most)
}
進行初始化,之所以看到運動中圓弧能夠在右邊增長的同時,左邊的也在減少是使用pathmeasure類中的getsegment方法來擷取任意一段長度的路徑。
private
void
init(context context, attributeset attrs)
pm2.getsegment()方法可以獲取指定長度的路徑,然後儲存在path中,在第二步已經把乙個圓加到path中去,並初始化了pm2了。
/**靜態的笑臉
*@param canvas
*/private
void
first(canvas canvas)
/**一開始畫的眼睛
*@param canvas
*/public
void
draweye(canvas canvas)
這裡記得要進行角度轉換,π=180
/**從底部開始畫乙個在運動的圓,運動時間為0-3/4
* 即從270度開始,逆時針到0度
*@param canvas
*/private
void
drawcircle(canvas canvas)
在圓形運動到左眼的位置時,同時繪製左眼,時間為1/4+1/8=3/8
運動到右眼位置時繪製右眼,時間為1/4+1/8+1/4=5/8
兩個眼睛的位置都設為45度
/* @param canvas
* @param pos 0代表畫左眼,1代表畫右眼
*/public
void
drawoneeye(canvas canvas, int pos) else
if(pos==1)
}
笑臉部分是半個圓,因此擷取的最大長度是length/2
用的時間是1/2,畫完之後fraction應該到了5/4的時間了,1/4+1/8+1/4+1/8+1/2=5/4
public
void
drawface(canvas canvas)
把圓臉部分逆時針旋轉起來,擷取最大長度還是length/2, 用的是這個方法pm2.getsegment(),運動的時間為1/4時間,需要不斷改變起點和終點,這樣圓臉才會動起來
public
void
rotateface(canvas canvas)
剩下的1/4時間,就用另外乙個pathmeasure,這個圓的路徑起點是底部的,在初始化時候已經進行轉換,因為這樣設定比較方便的計算它的終點位置。
public
void
drawlastfact(canvas canvas)
public
void
performanim()
});val.setrepeatcount(repeacount);
val.start();
val.setrepeatmode(valueanimator.restart);
}
這裡的fraction的範圍是[0,2],每個片段就用分數表示,最後它們的和剛好是2。
@override
protected
void
onlayout(boolean changed, int left, int top, int right,
int bottom) }}
@override
protected
void
ondraw(canvas canvas)
//畫左眼
if (fraction > 1.0 * 3 / 8&&fraction<1.0*6/4)
//畫右眼
if(fraction>1.0*5/8&&fraction<1.0*6/4)
//畫臉
if(fraction>=0.75&&fraction<=5.0/4)
//把臉運動起來
if(fraction>=5.0/4&&fraction<=(5.0/4+1.0/4))
if(fraction>=6.0/4)
}
/**
* 根據手機的解析度從 dp 的單位 轉成為 px(畫素)
*/public
intdip2px(context context, float dpvalue)
//字段
private
final
int blue = 0xff4aadff;
private
int mwidth = 200;
private
int mheight = 200;
private
int radius = 20;
private
int linewidth = 5;
private
float eyeradius;
paint paint,eyepaint;
drawfilter drawfilter;
path path, pathcircle,pathcircle2;
pathmeasure pm,pm2;
float length;// 圓周長
float fraction = -1;
long duration = 2000;
int repeacount = 8;
float x = 0, y = 0;
valueanimator val;
//在布局中的設定
.example
.test22.view
.smileview
android:id="@+id/smile"
android:layout_width="match_parent"
android:layout_height="100dp"/>
在activity中,
smileview smile;
smile = (smileview)findviewbyid(r.id
.smile);
//設定動畫執行時間,重複的次數。
smile.setduration(2000);
smile.setrepeacount(8);
//執行動畫
smile.performanim();
//停止動畫
smile.cancelanim();
我覺得難點在於運動中圓弧的一邊增長的同時,另一邊在縮短的控制,計算的不好就很容易出現從乙個片段到另外乙個片段時候跳躍十分明顯,在這裡我用到兩個路徑的圓,乙個圓的起點在最右邊,乙個圓起點在底部,這樣在處理最後那部分,片段的終點需要回到底部時候比較方便。重點在於pathmeasure類的getsegment()方法的運用,同時會改變預設路徑的起點。 仿支付寶支付成功動畫
與支付寶支付成功後類似的乙個動畫,本人小白乙隻大神請繞過,畫的菜大家見諒 直接將view拷貝進專案中即可,動畫開關為loadcircle和stop方法,提供了監聽介面ondonecircleanimlistner以便於和外部邏輯銜接 import android.animation.animator...
PathMeasure 仿支付寶支付動畫
在 android 自定義 view 中,path 可能用的比較多,pathmeasure 可能用的比較少,就我而言,以前也沒有使用過 pathmeasure 這個 api,看到別人用 pathmeasure 和 valueanimator 結合在一起完成了很好的動畫效果,於是我也學習下 pathm...
仿支付寶輸入支付密碼2(帶動畫)
先看看效果圖把 主介面只有這麼簡單,就不多在去介紹了 button button findviewbyid r.id.home button background view findviewbyid r.id.home background button.setonclicklistener new...