前言
為什么起了這么個標題呢绳匀,因為我們接下來要做的動畫運用到了多個知識點,如果自己實操幾遍,基本android中繪圖方面的知識點就掌握的差不多了
先看下動畫圖
首先讓我們來看一下動畫效果 ,原文地址
有教程了為什么還要專門再寫一篇疾棵?因為小編腦子比較笨戈钢,理解不了原文寫的啥意思,就寫了另一種實現(xiàn)方法是尔,本文通俗易懂殉了,不懂留言即可
分析動畫
- 1、加載過程拟枚,畫藍色圓環(huán)薪铜,當進度為100%時,圓環(huán)完成
- 2恩溅、從右側拋出藍色小方塊隔箍,小方塊沿著曲線到達圓環(huán)正上方
- 3、藍色小方塊下落脚乡,下落過程中蜒滩,逐漸變長,當方塊與圓圈接觸時奶稠,進入圓環(huán)的部分變粗帮掉,同時圓環(huán)逐漸被擠壓,變成橢圓形
- 4窒典、方塊底端到達圓環(huán)中心后蟆炊,發(fā)出三個分叉向圓周延伸,同時橢圓被撐大瀑志,逐漸恢復回圓形
- 5涩搓、圓環(huán)變綠色,畫出綠色勾√
仔細分析一下第一部分劈猪,則是canvas.drawArc就可以昧甘,隨著進度改變初始位置,和弧長
第二部分也不難沒和第一部分基本一樣战得,只不過圓變大了
第三部分算是最難的部分了充边,先路徑,判斷
第一部分常侦、隨進度增加圓弧增加浇冰,最后成圓
上面我們分析也提到,實現(xiàn)并不難聋亡,這里我們用handle的定時原理來代替進度
MainActivity
public void button(View view){
switch (view.getId()){
case R.id.btn2:
//定時器原理
final Handler handler=new Handler();
i=0;
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (i<360){
i+=10;
mMyView.setProgress(i);
handler.postDelayed(this,100);
}else {
mMyView.finishSuccess();
}
}
},1000);
}
}
然后在我們的自定義MyView中肘习,設置setProgress參數(shù),收到進度值,刷新頁面坡倔,onDrow更新進度值漂佩,繪制圓弧隨進度改變
/**
* 開始完成動畫
*/
private void start(){
post(new Runnable() {
@Override
public void run() {
mRotateAnimation.start();
}
});
}
public void setProgress(int progress) {
status = 0;
this.progress = progress;
postInvalidate();
}
/**
* loading成功后調用
*/
public void finishSuccess() {
setProgress(maxProgress);
this.isSuccess = true;
status = 1;
start();
}
/**
* loading失敗后調用
*/
public void finishFail() {
setProgress(maxProgress);
this.isSuccess = false;
status = 1;
start();
}
}
重寫onSizeChanged
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mWidth = w;
mHeight = h;
//居中設置 圓的半徑 小編這里的半徑為130
radius = Math.min(getMeasuredWidth(),getMeasuredHeight())/4-strokeWidth;
//居中繪圓 小編這里的圓為150脖含,150,410投蝉,410
mRectF.set(new RectF(radius+strokeWidth, radius+strokeWidth, 3 * radius+strokeWidth, 3 * radius+strokeWidth));
}
重寫onDraw
圓弧起始狀態(tài)
圓弧最終狀態(tài)
可以看到养葵,首先圓弧有一定的起始角度,我們知道瘩缆,在Android坐標系中港柜,0度其實是指水平向右開始的 也就是起點的起始角度,其實是-90度咳榜,終點的起始角度,其實-150度
而整個過程中爽锥, 起點:-90度涌韩,逆時針旋轉270度,最后回到0度位置 終點:-150度氯夷,與起點相差60度臣樱,最后相差360度,與起點重合
所以當progress=1腮考,也就是動畫完成時雇毫,起點會減去270度,那么對應每個progress 起點的位置應該是
-90-270*progress
當progress=1,終點和起點相差360度踩蔚,而一開始就相差60度,所以整個過程就是多相差了300度棚放,那么對應每個progress,終點和起點應該相差
-(60+precent*300)
根據(jù)上面的結論馅闽,我們得到圓弧的具體繪制方式如下:
@Override
protected void onDraw(Canvas canvas) {
switch (status){
case 0:
//設置一下maxProgress最大為360(private int maxProgress=360飘蚯;),這里設置多少無所謂福也,設置360局骤,方便理解
float precent = 1.0f*progress/maxProgress;
canvas.drawArc(mRectF, startAngle-270*precent, -(60 + precent*300), false, circlePaint);
break;
當然我們要在初始化的時候定義一下paint
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.argb(255, 48, 63, 159));
circlePaint.setStrokeWidth(strokeWidth);
circlePaint.setStyle(Paint.Style.STROKE);
第一部分完成,看一下效果圖
圓弧運動狀態(tài)
第二部分暴凑、拋出小方塊
首先構思如何繪出小方塊峦甩,其實方法有多種,可以用canvas的drawLine现喳,也可以drawArc凯傲,小編這里用的是drawArc,有開始角度嗦篱,和橫掃角度泣洞,這樣會很方便的控制移動,而用drawLine會很麻煩默色,原文用的drawLine球凰,反正我是沒有看懂狮腿,如果你看懂了,可以留言教教我
先看一張小編用軟件繪制的圖呕诉,我們可以看出深藍色的圓為小圓缘厢,紅色的為大圓(沒畫完整),那么大圓的弧度右上部分就是小方塊的運動軌跡
第一種方法
1.假設運動軌跡是某個圓的一段弧甩挫,那么根據(jù)勾股定理有如下方程
(X+R)^2 + (2R)^2 = (X+2R)^2
2.解得X=R/2(其實也很容易解贴硫,就是勾三股四玄五) ,小編這里的R為130(上面有寫到),我們只需要知道圓心角是多少度伊者,就可以設置運動軌跡了
弦長為(R)^2 + (2R)^2 =L^2,解L=根5 * R
3.已知弦長L和半徑R求大圓半徑:
sinA=(1/2)*L/R=L/(2R),圓心角=2asin(L/(2R))
圓心角*180/π=度數(shù) 即2asin(L/(2R))*180/π=度數(shù)
Android中這樣表示
(2*Math.asin(290.68/650))*180/Math.PI
第二種方法
這也是最好用的方法英遭,反正原文作者的那種我是看不懂
如果勾股定理你已經(jīng)忘得一干二凈了,那么你也可以直接運用Android的度數(shù)公式
那么如何計算任意兩點間直線的傾斜角呢?只需要將兩點x,y坐標分別相減得到一個新的點(x2-x1,y2-y1)亦渗。然后利用它求出角度即可——Math.atan2(y2-y1,x2-x1)挖诸。
Math.atan2(y2-y1,x2-x1) * 180.0 / Math.PI
//拋出動畫
System.out.println(endAngle);
mRotateAnimation = ValueAnimator.ofFloat(0f, (float)(Math.atan2(-260, 195) * 180.0 / Math.PI));
mRotateAnimation.setDuration(1000);
mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
curSweepAngle = (float) animation.getAnimatedValue();
invalidate();
}
});
//設置監(jiān)聽
mRotateAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
curSweepAngle = 0;
if (isSuccess) {
status = 2;
mDownAnimation.start();
} else {
status = 5;
mCommaAnimation.start();
}
}
});
我們的小方塊就這樣完成了
方塊下落,壓縮圓環(huán)
可以說下落過程法精,是整個動畫中最復雜的過程了多律,包括方塊下落,圓環(huán)擠壓搂蜓,方塊變粗三個過程狼荞,整個過程,從方塊下落開始帮碰,到方塊底部到底圓心