????????轉(zhuǎn)眼已經(jīng)18年底了,在Androd這行已經(jīng)混了3年荐吵,一直說寫些東西骑冗,總是沒有執(zhí)行赊瞬。有想法的時候沒時間,有時間的時候沒想法贼涩,今天終于開始寫一些東西了巧涧。
? ????? 回首Androd,自定義View是使用最多的遥倦,也是我第一次有計劃的去學(xué)習(xí)和整理的模塊谤绳。以下是我總結(jié)的自定義View的一些用法,沒有涉及底層原理袒哥。
一:自定義View需要重新的2個方法缩筛。
?1、onMeasure 方法
? ? ? ? 通過onMeasure方法可以得到父類的specMode和size
? 1.1堡称、當(dāng)父View的specMode為EXACTLY的時候:父View強加給子View一個確切的大小,有如下兩種情況
?????? 1.1.1) 子View的layout_width或者layout_height設(shè)置為MATCH_PARENT的時候瞎抛,子View的specMode為EXACTLY
?????? 1.1.2) 子View的layout_width或者layout_height設(shè)置為WRAP_CONTENT的時候,子View的specMode為AT_MOST
?????? 1.1.3) 不論子view為match_parent或者wrap_content却紧,resultSize都等于父類的size.
? 1.2桐臊、當(dāng)父view的specMode為AT_MOST的時候:父View強加給一個最大的size給子view,最大的size也就是父view的size
?????? 1.2.1) 此時不論子view的為match_parent或者wrap_content晓殊,子view的specMode都為AT_MOST
?????? 1.2.2) resultSize的大小被設(shè)置為父view的大小
? 1.3断凶、當(dāng)父view的specMode為UNSPECIFIED的時候:
?????? 1.3.1) 此時不論子view的為match_parent或者wrap_content,子view的specMode都為UNSPECIFIED
?????? 1.3.2) 此時reusltSize = 0
2巫俺、onDraw方法
2.1认烁、畫筆
mPaint = new Paint(); //初始化
1、mPaint.setAntiAlias(true);//去除邊緣鋸齒识藤,優(yōu)化繪制效果
2砚著、mPaint.setColor(Color.BLACK);//設(shè)置顏色
3、setStrokeWidth(float width)?//設(shè)置畫筆寬度?
4痴昧、//設(shè)置線冒樣式稽穆,取值有Cap.ROUND(圓形線冒)、Cap.SQUARE(方形線冒)赶撰、Cap.BUTT(無線冒)?
????//注意:冒多出來的那塊區(qū)域就是線帽舌镶!就相當(dāng)于給原來的直線加上一個帽子一樣,所以叫線帽?
????setStrokeCap(Paint.Cap cap)
5豪娜、//設(shè)置線段連接處樣式餐胀,取值有:Join.MITER(結(jié)合處為銳角)、Join.Round(結(jié)合處為圓弧)瘤载、Join.BEVEL(結(jié)合處為直線)?
????setStrokeJoin(Paint.Join join)?
6否灾、//設(shè)置筆畫的傾斜度,90度拿畫筆與30拿畫筆鸣奔,畫出來的線條樣式肯定是不一樣的吧墨技。
????setStrokeMiter(float miter)?
7惩阶、void reset() //清空畫筆復(fù)位。
8扣汪、void set(Paint src)?//設(shè)置一個外來Paint畫筆
9断楷、//獲取與設(shè)置alpha值、顏色崭别、ARGB等冬筒。
????void setARGB(int a, int r, int g, int b)
????int getAlpha()
????void setAlpha(int a)
????int getColor()
????void setColor(int color)
10、//獲取與設(shè)置是否使用抗鋸齒功能茅主,會消耗較大資源舞痰,繪制圖形速度會變慢,一般會開啟暗膜。設(shè)置后會平滑一些匀奏;
????void setAntiAlias(boolean aa)?
11、//獲取與設(shè)定是否使用圖像抖動處理学搜,會使繪制出來的圖片顏色更加平滑和飽滿、圖像更加清晰论衍。
????final boolean isDither()
? ? void setDither(boolean dither)?
12瑞佩、setPathEffect(PathEffect effect) //設(shè)置繪制路徑的效果
13、CornerPathEffect //圓形拐角效果
14坯台、paint.setPathEffect(newCornerPathEffect(100));//利用半徑R=50的圓來代替原來兩條直線間的夾角
15炬丸、DashPathEffect //虛線效果
16、//設(shè)置圖形重疊時的處理方式蜒蕾,如合并稠炬,取交集或并集,經(jīng)常用來制作橡皮的擦除效果
????setXfermode(Xfermode xfermode)
17咪啡、//設(shè)置MaskFilter首启,可以用不同的MaskFilter實現(xiàn)濾鏡的效果,如濾化撤摸,立體等
????setMaskFilter(MaskFilter maskfilter)
18、//設(shè)置顏色過濾器准夷,可以在繪制顏色時實現(xiàn)不用顏色的變換效果
????setColorFilter(ColorFilter colorfilter)
19钥飞、//設(shè)置圖像效果,使用Shader可以繪制出各種漸變效果
????setShader(Shader shader)
20衫嵌、//在圖形下面設(shè)置陰影層读宙,產(chǎn)生陰影效果,radius為陰影的角度楔绞,dx和dy為陰影在x軸和y軸上的距離结闸,color為陰影的顏色
????setShadowLayer(float radius ,float dx,floatdy,int color)
21掖棉、//設(shè)置畫筆樣式1.
????Paint.Style.FILL :填充內(nèi)部
????Paint.Style.FILL_AND_STROKE:填充內(nèi)部和描邊
????Paint.Style.STROKE :僅描邊、
2.2膀估、畫圓
1. canvas.drawCircle(cx, cy, radius,;//外圓
mPaint.setColor(Color.WHITE);
canvas.drawCircle(cx, cy, radius - mBorderWidth, mPaint);//內(nèi)圓
2.3幔亥、繪畫弧形圓
//畫上面黑色半圓
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLACK);
RectF blackHalfRect = new RectF(cx - 45, cy - 90, cx + 45, cy);
canvas.drawArc(blackHalfRect, 270, 180, true, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.WHITE);
RectF whiteHalfRect = new RectF(cx - 45, cy, cx + 45, cy + 90);
canvas.drawArc(whiteHalfRect, 270, -180, true, mPaint);
?? 2.4、繪畫半圓
RectF mRectf = new RectF(left, top, right,botton);
mPaint.setColor(Color.WHITE);
canvas.drawArc(mRectf, 270, 180, true, mPaint);
mPaint.setColor(Color.BLACK);
canvas.drawArc(mRectf, 270, -180, true, mPaint);
?? 2.5察纯、貝塞爾曲線
??? 2.5.1帕棉、什么是貝塞爾曲線
??? 貝塞爾曲線(Bézier?curve),又稱貝茲曲線或貝濟埃曲線饼记,是應(yīng)用于二維圖形應(yīng)用程序的數(shù)學(xué)曲線香伴。一般的矢量圖形軟件通過它來精確畫出曲線,貝茲曲線由線段與節(jié)點組成具则,節(jié)點是可拖動的支點即纲,線段像可伸縮的皮筋,我們在繪圖工具上看到的鋼筆工具就是來做這種矢量曲線的博肋。主要結(jié)構(gòu):起始點低斋、終止點(也稱錨點)、控制點匪凡。通過調(diào)整控制點膊畴,貝塞爾曲線的形狀會發(fā)生變化。
??? 2.5.2病游、貝塞爾曲線的分類
??? 2.5.2.1唇跨、一階貝塞爾曲線(線段):
??? 公式:
??? 原理:
??? 由?P0?至?P1?的連續(xù)點,?描述的一條線段
??? 2.5.2.2衬衬、二階貝塞爾曲線(拋物線):
??? 公式:
??? 原理:
??? 由?P0?至?P1?的連續(xù)點?Q0买猖,描述一條線段。
????由?P1?至?P2?的連續(xù)點?Q1滋尉,描述一條線段玉控。
????由?Q0?至?Q1?的連續(xù)點?B(t),描述一條二次貝塞爾曲線兼砖。
??? 2.5.2.3奸远、三階貝塞爾曲線:
??? 公式:
??? 原理:
?? 2.5.3、貝塞爾曲線的代碼實現(xiàn)
?? quadTo()方法從上一個點為起點開始繪制貝塞爾曲線讽挟,其中(x1懒叛,y1)為輔 助控制點,(x2耽梅,y2)為終點薛窥。
??? Path?mPath?=?new?Path();
??? mPath.moveTo(x0,y0);
??? mPath.quadTo(x1,y1,x2,y2);
? ? 如調(diào)用以上代碼,即繪制起點(x0,y0)诅迷,終點(x2佩番,y2),輔助控制點(x1罢杉,y1)的貝塞爾曲線趟畏。因此,通過不斷改變這三個點的位置滩租,我們可以繪制出各種各樣的曲線赋秀。
???? cubicTo()方法從上一個點為起點開始繪制三階貝塞爾曲線,其中(x1律想,y1),(?x2,?y2?)為輔助控制點猎莲,(x3,y3)為終點技即。
?? 2.5.4著洼、貝塞爾曲線的應(yīng)用
??? 2.5.4.1、波浪紋
??? 要實現(xiàn)一個波浪不斷涌動的效果而叼,這種效果在很多手機應(yīng)用中可見身笤,例如手機電量,內(nèi)存剩余等澈歉。類似這種需要實現(xiàn)波浪的效果展鸡,我們需要繪制帶有平滑自然效果的曲線,這時候就需要貝塞爾曲線來輔助了埃难。
??? 原理圖:
???????? 圖中的矩陣即為視圖的可見范圍,也就是我們手機常見的區(qū)域涤久。通過屬性動畫類ValueAnimator不斷改變點1的橫坐標(biāo)涡尘,隨著點1橫坐標(biāo)向右移動,點2响迂,點3考抄,點4,點5蔗彤,以及四個控制點的坐標(biāo)隨著點1的移動同時位移相同距離川梅,每一次坐標(biāo)點更新,我們調(diào)用一次invalidate()方法然遏,調(diào)用draw重新繪制視圖贫途,繪制四段貝塞爾曲線。最后點1移動到原先點3的位置待侵,這樣就完成了一次動畫丢早。
????這樣,通過循環(huán)不斷的動畫效果,我們就實現(xiàn)了波浪的效果怨酝。
??? 2.5.4.2傀缩、粘連體
??? 利用二階貝塞爾曲線還可以實現(xiàn),類似兩種物體粘合在一起的效果农猬,比如我們常用的qq赡艰,在qq聊天列表上有一個非常有意思的功能,就是當(dāng)我們用手指移動聊天列表上的未讀消息標(biāo)志的時候斤葱,它與聊天列表會產(chǎn)生粘連的效果:
????現(xiàn)在慷垮,我們來模擬這種效果,利用學(xué)到的二階貝塞爾曲線來繪制苦掘。
??? 我們看到原理圖换帜,基本構(gòu)造為兩個圓,和兩端貝塞爾曲線鹤啡,繪制貝塞爾曲線惯驼,由于這是一個二階的貝塞爾曲線,我們只需要一個控制點递瑰,在這個圖里祟牲,我們的兩條貝塞爾曲線的兩個控制點分別為(x1,y1)(x4,?y4)的中點,(x2,?y2)(x3,?y3)的中點抖部。
??? 從圖中可以看出说贝,我們的貝塞爾曲線由我們的控制點控制,控制點又是被起點和終點控制著慎颗,因此乡恕,當(dāng)兩個圓距離越大,曲線越趨于平緩俯萎,當(dāng)兩個圓距離越小傲宜,曲線的波動度越大,這樣夫啊,我們想要的粘連的效果就實現(xiàn)了函卒。另外,這里有一個還有角度(圖中的45度角)可以用來控制撇眯,也可以作為控制曲線波動度的參數(shù)报嵌。
??? 通過以上分析,我們通過一個方法來繪制兩個圓之間的粘連體路徑:
??? 我們給控件設(shè)置一個粘連的最大距離熊榛,即如果兩個圓之間的距離超過這個值锚国,則不再繪制粘連體。
??? 2.5.4.3来候、彈性球
??? 三階貝塞爾曲線跷叉,就是有兩個控制點,它相比二階曲線的優(yōu)點是,由于控制點的增加云挟,它能夠更加輕松地繪制出更平滑更自然的曲線梆砸。
??? 如何繪制類似這種,看起來具有彈性球的滑動球园欣,我們需要使用三階貝塞爾曲線赏寇,那么首先如何用三階貝塞爾曲線繪制出一個圓秃臣,這里有一篇文章兴垦,是關(guān)于如何用貝塞爾曲線繪制圓:http://spencermortensen.com/articles/bezier-circle/?茵汰,大概意思是講,我們需要一個值就是c?=?0.552284749绑榴,如下圖哪轿,要繪制右上角的圓弧,我們需要兩個控制點翔怎,其中B就是一個控制點窃诉,我們需要保證AB?=?c?*r,即可以畫出1/4的圓弧赤套,以此類推飘痛,連續(xù)畫四段這樣的圓弧,就可以畫出一個標(biāo)準(zhǔn)的圓容握。
??? 接下來我們觀察彈性球的運動宣脉,大概可以分為以下幾個階段:
1)開始啟動,此時右邊點位移剔氏,其他點不動
2)開始加速
3)減速
4)到達(dá)終點
5)回彈效果
上面完成了一個彈性球的封裝塑猖,可以實現(xiàn)四個方向的運動,然后我們實現(xiàn)一個彈性球的loader
package?com.zero.bezier.widget.elastic;
import?android.animation.Animator;??
import?android.animation.ValueAnimator;??
import?android.graphics.Path;??
import?android.graphics.PointF;??
import?android.view.animation.AccelerateDecelerateInterpolator; ?
/**?
*?彈性球?
*?@author?linzewu?
*?@date?2016/6/1?
*/??
public?class?ElasticBall?extends?Ball?{??
/**?
?*?向上運動?
?*/??
private?static?final?int?DIRECTION_UP?=?1;??
?/**?
?*?向下運動?
? */??
private?static?final?int?DIRECTION_DOWN?=?2;??
?/**?
*?向左運動?
? */??
private?static?final?int?DIRECTION_LEFT?=?3;??
?/**?
?*?向右運動?
? */??
private?static?final?int?DIRECTION_RIGHT?=?4;??
?/**?
?*?運動方向?
?*/??
private?int?mDirection;??
/**?
*?動畫完成百分比(0~1)?
?*/??
private?float?mAnimPercent;??
?/**?
?*?彈性距離?
?*/??
private?float?mElasticDistance;??
?/**?
*?彈性比例?
*/??
private?float?mElasticPercent?=?0.8f;??
?/**?
*?位移距離?
*/??
private?float?mMoveDistance;??
/**?
*?動畫消費時間?
?*/??
private?long?mDuration?=?1500;??
?/**?
*?偏移值?
*/??
private?float?offsetTop,?offsetBottom,?offsetLeft,?offsetRight;??
/**?
*?圓形偏移比例?
*/??
private?float?c?=?0.551915024494f;??
private?float?c2?=?0.65f;??
?/**?
*?動畫開始點?
*/??
private?Ball?mStartPoint;??
/**?
*?動畫結(jié)束點?
*/??
private?Ball?mEndPoint;??
?/**?
?*?構(gòu)造方法?
?*?
*?@param?x?圓心橫坐標(biāo)?
*?@param?y?圓心縱坐標(biāo)?
*?@param?radius?圓半徑?
*/??
public?ElasticBall(float?x,?float?y,?float?radius)?{??
super(x,?y,?radius);??
init();??
?}??
private?void?init()?{??
mElasticDistance?=?mElasticPercent?*?radius;??
offsetTop?=?c?*?radius;??
offsetBottom?=?c?*?radius;??
offsetLeft?=?c?*?radius;??
offsetRight?=?c?*?radius;??
}??
public?interface?ElasticBallInterface{??
void?onChange(Path?path);??
void?onFinish();??
} ?
private?ElasticBallInterface?mElasticBallInterface; ?
/**?
*?對外公布方法谈跛,設(shè)置彈性比例?(0~1)?
?*?@param?elasticPercent?
?*/??
?public?void?setElasticPercent(float?elasticPercent)?{??
?this. mElasticPercent=?elasticPercent;?
?}??
?/**?
*?對外公布方法萌庆,設(shè)置動畫時間?
*?@param?duration?
?*/??
public?void?setDuration(long?duration)?{??
?this.mDuration?=?duration;??
?}??
/**?
?*?對外公布方法,?開啟動畫?
*?@param?endPoint?
*/??
public?void?startElasticAnim(PointF?endPoint,?ElasticBallInterface?elasticBallInterface)?{??
this.mEndPoint?=?new?ElasticBall(endPoint.x,?endPoint.y,?radius);??
this.mStartPoint?=?new?ElasticBall(x,?y,?radius);??
this.mStatusPoint1?=?new?ElasticBall(x,?y,?radius);??
this.mStatusPoint2?=?new?ElasticBall(x,?y,?radius);??
this.mStatusPoint3?=?new?ElasticBall(x,?y,?radius);??
this.mStatusPoint4?=?new?ElasticBall(x,?y,?radius);??
this.mStatusPoint5?=?new?ElasticBall(x,?y,?radius);??
this.mElasticBallInterface?=?elasticBallInterface;??
judgeDirection();??
mMoveDistance?=?getDistance(mStartPoint.x,?mStatusPoint1.y,?endPoint.x,?endPoint.y);??
animStatus0();??
ValueAnimator?valueAnimator?=?ValueAnimator.ofFloat(0,?1); ?
valueAnimator.setDuration(mDuration); ?
valueAnimator.setInterpolator(new?AccelerateDecelerateInterpolator());??
valueAnimator.start();??
valueAnimator.addUpdateListener(new?ValueAnimator.AnimatorUpdateListener()?{??
@Override??
public?void?onAnimationUpdate(ValueAnimator?animation)?{??
mAnimPercent?=?(float)?animation.getAnimatedValue();??
if(mAnimPercent>=0?&&?mAnimPercent?<=?0.2){??
animStatus1();??
?} ?else?if(mAnimPercent?>?0.2?&&?mAnimPercent?<=?0.5){ ?
animStatus2();??
?} ?else?if(mAnimPercent?>?0.5?&&?mAnimPercent?<=?0.8){ ?
?animStatus3();??
?} ?else?if(mAnimPercent?>?0.8?&&?mAnimPercent?<=?0.9){ ?
animStatus4();??
?} ??else?if(mAnimPercent?>?0.9&&mAnimPercent?<=?1){ ?
?animStatus5();??
?}??
?if?(mElasticBallInterface?!=?null)?{??
?mElasticBallInterface.onChange(drawElasticCircle(topX,?topY,?offsetTop,?offsetTop,??
?bottomX,?bottomY,?offsetBottom,?offsetBottom,??
leftX,?leftY,?offsetLeft,?offsetLeft,??
?rightX,?rightY,?offsetRight,?offsetRight));??
?}??
}??
?});??
?valueAnimator.addListener(new?Animator.AnimatorListener()?{??
@Override??
public?void?onAnimationStart(Animator?animation)?{??
?} ?
@Override??
?public?void?onAnimationEnd(Animator?animation)?{??
if?(mElasticBallInterface?!=?null)?{??
mElasticBallInterface.onFinish();??
?}??
} ?
@Override??
public?void?onAnimationCancel(Animator?animation)?{ ?
? } ?
@Override??
?public?void?onAnimationRepeat(Animator?animation)?{ ?
}??
?});??
} ?
?private?void?judgeDirection()?{??
if?(mEndPoint.x?-?mStartPoint.x?>?0)?{??
mDirection?=?DIRECTION_RIGHT;??
}else?if?(mEndPoint.x?-?mStartPoint.x?<?0)?{??
mDirection?=?DIRECTION_LEFT;??
}else?if?(mEndPoint.y?-?mStartPoint.x?>?0)?{??
?mDirection?=?DIRECTION_DOWN;??
?}else?if?(mEndPoint.y?-?mStartPoint.y?<?0){??
mDirection?=?DIRECTION_UP;??
?}??
? } ?
/**
?*?動畫狀態(tài)0?(初始狀態(tài):圓形)?
?*/??
?private?void?animStatus0()?{??
offsetTop?=?c?*?radius;??
offsetBottom?=?c?*?radius;??
offsetLeft?=?c?*?radius;??
offsetRight?=?c?*?radius;??
?}??
?private?Ball?mStatusPoint1; ?
/**?
*?動畫狀態(tài)1?(0~0.2)?
?*/??
private?void?animStatus1()?{??
?float?percent?=?mAnimPercent?*?5f;??
if?(mDirection?==?DIRECTION_LEFT)?{??
?leftX?=?mStartPoint.leftX?-?percent?*?mElasticDistance;??
}?else?if?(mDirection?==?DIRECTION_RIGHT)?{??
rightX?=?mStartPoint.rightX?+?percent?*?mElasticDistance;??
?}?else?if?(mDirection?==?DIRECTION_UP)?{??
?topY?=?mStartPoint.topY?-?percent?*?mElasticDistance;??
?}?else?if?(mDirection?==?DIRECTION_DOWN)?{??
? bottomY?=?mStartPoint.bottomY?+?percent?*?mElasticDistance;??
?}??
?mStatusPoint1.refresh(x,?y,?topX,?topY,?bottomX,?bottomY,??
? leftX,?leftY,?rightX,?rightY);??
? }??
private?Ball?mStatusPoint2; ?
?/**?
?*?動畫狀態(tài)2?(0.2~0.5)?
? */??
?private?void?animStatus2()?{??
?float?percent?=?(float)?((mAnimPercent?-?0.2)?*?(10f?/?3));??
?if?(mDirection?==?DIRECTION_LEFT)?{??
?leftX?=?mStatusPoint1.leftX?-?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?x?=?mStatusPoint1.x?-?percent?*?(mMoveDistance?/?2);??
rightX?=?mStatusPoint1.rightX?-?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?topX?=?x;??
?bottomX?=?x;??
//偏移值稍作變化??
?offsetTop?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
offsetBottom?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
}?else?if?(mDirection?==?DIRECTION_RIGHT)?{??
?rightX?=?mStatusPoint1.rightX?+?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?x?=?mStatusPoint1.x?+?percent?*?(mMoveDistance?/?2);??
leftX?=?mStatusPoint1.leftX?+?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?topX?=?x;??
?bottomX?=?x;??
//偏移值稍作變化??
?offsetTop?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
offsetBottom?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
}?else?if?(mDirection?==?DIRECTION_UP)?{??
?topY?=?mStatusPoint1.topY?-?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
y?=?mStatusPoint1.y?-?percent?*?(mMoveDistance?/?2);??
bottomY?=?mStatusPoint1.bottomY?-?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?leftY?=?y;??
?rightY?=?y;??
?//偏移值稍作變化??
offsetLeft?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
offsetRight?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
}?else?if?(mDirection?==?DIRECTION_DOWN)?{??
bottomY?=?mStatusPoint1.bottomY?+?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?y?=?mStatusPoint1.y?+?percent?*?(mMoveDistance?/?2);??
?topY?=?mStatusPoint1.topY?+?percent?*?(mMoveDistance?/?2?-?mElasticDistance?/?2?);??
?leftY?=?y;??
rightY?=?y;??
?//偏移值稍作變化??
offsetLeft?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
?offsetRight?=?radius?*?c?+?radius?*?(?c2?-?c?)?*?percent;??
? }??
?mStatusPoint2.refresh(x,?y,?topX,?topY,?bottomX,?bottomY,??
?leftX,?leftY,?rightX,?rightY);??
?} ?
private?Ball?mStatusPoint3; ??
?/**?
?*?動畫狀態(tài)3?(0.5~0.8)?
? */??
private?void?animStatus3()?{??
float?percent?=?(mAnimPercent?-?0.5f)?*?(10f?/?3f);??
?if?(mDirection?==?DIRECTION_LEFT)?{??
? leftX?=?mStatusPoint2.leftX?-?Math.abs(percent?*?(mEndPoint.rightX?-?mStatusPoint2.rightX)); ?
x?=?mStatusPoint2.x?-?Math.abs(percent?*?(mEndPoint.x?-?mStatusPoint2.x));??
?rightX?=?mStatusPoint2.rightX?-?Math.abs(percent?*?(mEndPoint.x?-?mStatusPoint2.x));??
?topX?=?x;??
?bottomX?=?x;??
?//偏移值稍作變化??
?offsetTop?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
?offsetBottom?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
? }?else?if?(mDirection?==?DIRECTION_RIGHT)?{??
rightX?=?mStatusPoint2.rightX?+?percent?*?(mEndPoint.rightX?-?mStatusPoint2.rightX);??
?x?=?mStatusPoint2.x?+?percent?*?(mEndPoint.x?-?mStatusPoint2.x);??
? leftX?=?mStatusPoint2.leftX?+?percent?*?(mEndPoint.x?-?mStatusPoint2.x);??
? topX?=?x;??
? bottomX?=?x;??
? ?//偏移值稍作變化??
? offsetTop?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
?offsetBottom?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
?}?else?if?(mDirection?==?DIRECTION_UP)?{??
topY?=?mStatusPoint2.topY?-?Math.abs(percent?*?(mEndPoint.topY?-?mStatusPoint2.topY)); ?
y?=?mStatusPoint2.y?-?Math.abs(percent?*?(mEndPoint.y?-?mStatusPoint2.y));??
?bottomY?=?mStatusPoint2.bottomY?-?Math.abs(percent?*?(mEndPoint.y?-?mStatusPoint2.y));??
leftY?=?y;??
?rightY?=?y;??
?//偏移值稍作變化??
offsetLeft?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
?offsetRight?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
?}?else?if?(mDirection?==?DIRECTION_DOWN)?{??
?bottomY?=?mStatusPoint2.bottomY?+?percent?*?(mEndPoint.bottomY?-?mStatusPoint2.bottomY); ?
?y?=?mStatusPoint2.y?+?percent?*?(mEndPoint.y?-?mStatusPoint2.y);??
?topY?=?mStatusPoint2.topY?+?percent?*?(mEndPoint.y?-?mStatusPoint2.y);??
leftY?=?y;??
rightY?=?y;??
//偏移值稍作變化??
?offsetLeft?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
offsetRight?=?radius?*?c2?-?radius?*?(?c2?-?c?)?*?percent;??
}??
mStatusPoint3.refresh(x,?y,?topX,?topY,?bottomX,?bottomY,??
?leftX,?leftY,?rightX,?rightY);??
?} ??
private?Ball?mStatusPoint4; ? ? ?
? /**?
? *?動畫狀態(tài)4?(0.8~0.9)?
? */??
private?void?animStatus4()?{??
?float?percent?=?(float)?(mAnimPercent?-?0.8)?*?10;??
??if?(mDirection?==?DIRECTION_LEFT)?{??
?rightX?=?mStatusPoint3.rightX?-?percent?*?(Math.abs(mEndPoint.rightX?-?mStatusPoint3.rightX)?+?mElasticDistance/2); ?
?//再做一次賦值币旧,防止和終點不重合??
?leftX?=?mEndPoint.leftX;??
x?=?mEndPoint.x;??
? bottomX?=?mEndPoint.bottomX;??
? topX?=?mEndPoint.topX;??
? }?else?if?(mDirection?==?DIRECTION_RIGHT)?{??
? leftX?=?mStatusPoint3.leftX?+?percent?*?(mEndPoint.leftX?-?mStatusPoint3.leftX?+??
? ? ?mElasticDistance/2);??
? ?//再做一次賦值,防止和終點不重合??
? ? ? ? ? ?rightX?=?mEndPoint.rightX;??
? ? ? ? ? ? x?=?mEndPoint.x;??
? ? ? ? ? ? bottomX?=?mEndPoint.bottomX;??
? ? ? ? ? ? topX?=?mEndPoint.topX;??
? ? ? ? }?else?if?(mDirection?==?DIRECTION_UP)?{??
? ? ? ? ? ? bottomY?=?mStatusPoint3.bottomY?-?percent?*?(Math.abs(mEndPoint.bottomY?-?mStatusPoint3??
? ? ? ? ? ? ? ? ? ?.bottomY)?+?mElasticDistance/2);??
? ? ? ? ? ? //再做一次賦值猿妈,防止和終點不重合??
? ? ? ? ? ?topY?=?mEndPoint.topY;??
? ? ? ? ? ?y?=?mEndPoint.y;??
? ? ? ? ? ?leftY?=?mEndPoint.leftY;??
? ? ? ? ? ?rightY?=?mEndPoint.rightY;??
? ? ? ?}?else?if?(mDirection?==?DIRECTION_DOWN)?{??
? ? ? ? ? ? topY?=?mStatusPoint3.topY?+?percent?*?(mEndPoint.topY?-?mStatusPoint3??
? ? ? ? ? ? ? ? ? ?.topY?+?mElasticDistance/2);??
? ? ? ? ? ? //再做一次賦值吹菱,防止和終點不重合??
? ? ? ? ? ? bottomY?=?mEndPoint.bottomY;??
? ? ? ? ? ?y?=?mEndPoint.y;??
? ? ? ? ? ?leftY?=?mEndPoint.leftY;??
? ? ? ? ? ?rightY?=?mEndPoint.rightY;??
? ? ? ? }??
? ? ? ? mStatusPoint4.refresh(x,?y,?topX,?topY,?bottomX,?bottomY,??
? ? ? ? ? ? ? ?leftX,?leftY,?rightX,?rightY);??
? ? }??
? ??private?Ball?mStatusPoint5;??
? ?/**?
? ? *?動畫狀態(tài)5?(0.9~1)回彈?
? ? ?*/??
? ?private?void?animStatus5()?{??
? ? ? ?float?percent?=?(float)?(mAnimPercent?-?0.9)?*?10;??
? ? ? ?if?(mDirection?==?DIRECTION_LEFT)?{??
? ? ? ? ? ?rightX?=?mStatusPoint4.rightX?+?percent?*?(mEndPoint.rightX?-?mStatusPoint4.rightX);??
? ? ? ?}?else?if?(mDirection?==?DIRECTION_RIGHT)?{??
? ? ? ? ? ?leftX?=?mStatusPoint4.leftX?+?percent?*?(mEndPoint.leftX?-?mStatusPoint4.leftX);??
? ? ? ?}?else?if?(mDirection?==?DIRECTION_UP)?{??
? ? ? ? ? ?bottomY?=?mStatusPoint4.bottomY?+?percent?*?(mEndPoint.bottomY?-?mStatusPoint4.bottomY);??
? ? ? ?}?else?if?(mDirection?==?DIRECTION_DOWN)?{??
? ? ? ? ? topY?=?mStatusPoint4.topY?+?percent?*?(mEndPoint.topY?-?mStatusPoint4.topY);??
? ? ? }??
? ? ? ?mStatusPoint5.refresh(x,?y,?topX,?topY,?bottomX,?bottomY,??
? ? ? ? ? ? ? ?leftX,?leftY,?rightX,?rightY);??
? }??
? ? /**?
? ? ?*?繪制彈性圓?
? ? *?通過繪制四段三階貝塞爾曲線,來實現(xiàn)有彈性變化的圓?
? ? ?*?@param?topX?
? ? *?@param?topY?
? ?*?@param?offsetTop1?
? ?*?@param?offsetTop2?
? ? *?@param?bottomX?
? ?*?@param?bottomY?
? ?*?@param?offsetBottom1?
? ? *?@param?offsetBottom2?
? ? ?*?@param?leftX?
? ? *?@param?leftY?
? ? *?@param?offsetLeft1?
? ?*?@param?offsetLeft2?
? ? ?*?@param?rightX?
? ? ?*?@param?rightY?
? ?*?@param?offsetRight1?
? ?*?@param?offsetRight2?
? ?*?@return?
? ?*/??
? ??private?Path?drawElasticCircle(??
? ? ? ? ? ??float?topX,?float?topY,?float?offsetTop1,?float?offsetTop2,??
? ? ? ? ? ??float?bottomX,?float?bottomY,?float?offsetBottom1,?float?offsetBottom2,??
? ? ? ? ? ??float?leftX,?float?leftY,?float?offsetLeft1,?float?offsetLeft2,??
? ? ? ? ??float?rightX,?float?rightY,?float?offsetRight1,?float?offsetRight2??
?)?{??
? /**?
?*?繪制每一段三階貝塞爾曲線需要兩個控制點?
? */??
PointF?controlTop1,?controlTop2,?controlBottom1,?controlBottom2,??
?controlLeft1,?controlLeft2,?controlRight1,?controlRight2;??
controlTop1?=?new?PointF();??
controlTop1.x?=?topX?-?offsetTop1;??
?controlTop1.y?=?topY;??
controlTop2?=?new?PointF();??
controlTop2.x?=?topX?+?offsetTop2;??
?controlTop2.y?=?topY;??
controlBottom1?=?new?PointF();??
controlBottom1.x?=?bottomX?-?offsetBottom1;??
controlBottom1.y?=?bottomY;??
controlBottom2?=?new?PointF();??
?controlBottom2.x?=?bottomX?+?offsetBottom2;??
?controlBottom2.y?=?bottomY;??
?controlLeft1?=?new?PointF();??
controlLeft1.x?=?leftX;??
?controlLeft1.y?=?leftY?-?offsetLeft1;??
?controlLeft2?=?new?PointF();??
controlLeft2.x?=?leftX;??
?controlLeft2.y?=?leftY?+?offsetLeft2;??
controlRight1?=?new?PointF();??
controlRight1.x?=?rightX;??
?controlRight1.y?=?rightY?-?offsetRight1;??
?controlRight2?=?new?PointF();??
?controlRight2.x?=?rightX;??
?controlRight2.y?=?rightY?+?offsetRight2;??
Path?path?=?new?Path();??
?/**?
?*?繪制top到left的圓弧?
? */??
path.moveTo(topX,?topY);??
?path.cubicTo(controlTop1.x,?controlTop1.y,?controlLeft1.x,?controlLeft1.y,?leftX,?leftY);??
?/**?
*?繪制left到bottom的圓弧?
?*/??
path.cubicTo(controlLeft2.x?,controlLeft2.y,?controlBottom1.x,?controlBottom1.y,?bottomX, ?bottomY); ?
/**?
?*?繪制bottom到right的圓弧?
?*/??
? ? ? ?path.cubicTo(controlBottom2.x,?controlBottom2.y,?controlRight2.x,?controlRight2.y, ?rightX,?rightY); ?
? ? ? ?/**?
? ? ? ? *?繪制right到top的圓弧?
? ? ? ? ?*/??
? ? ? ?path.cubicTo(controlRight1.x,?controlRight1.y,?controlTop2.x,?controlTop2.y,?topX,?topY);??
return?path;??
} ?
? /**?
?*?求兩點之間的距離?
?*?@param?x1?第一個點的橫坐標(biāo)?
?*?@param?y1?第一個點的縱坐標(biāo)?
*?@param?x2?第二個點的橫坐標(biāo)?
*?@param?y2?第二個點的縱坐標(biāo)?
*?@return?兩點距離?
*/??
private?float?getDistance(float?x1,?float?y1,?float?x2,?float?y2)?{??
??return?(float)?Math.sqrt((x1?-?x2)?*?(x1?-?x2)?+?(y1?-?y2)?*?(y1?-?y2));??
} ??
}??