Android自定義View學(xué)習(xí)總結(jié)

????????轉(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));??

} ??

}??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彭则,一起剝皮案震驚了整個濱河市鳍刷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俯抖,老刑警劉巖输瓜,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡尤揣,警方通過查閱死者的電腦和手機搔啊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來北戏,“玉大人负芋,你說我怎么就攤上這事∈扔” “怎么了旧蛾?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蠕嫁。 經(jīng)常有香客問我锨天,道長,這世上最難降的妖魔是什么剃毒? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任病袄,我火速辦了婚禮,結(jié)果婚禮上迟赃,老公的妹妹穿的比我還像新娘陪拘。我一直安慰自己,他們只是感情好纤壁,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布左刽。 她就那樣靜靜地躺著,像睡著了一般酌媒。 火紅的嫁衣襯著肌膚如雪欠痴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天秒咨,我揣著相機與錄音喇辽,去河邊找鬼。 笑死雨席,一個胖子當(dāng)著我的面吹牛菩咨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陡厘,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼抽米,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了糙置?” 一聲冷哼從身側(cè)響起云茸,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谤饭,沒想到半個月后标捺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懊纳,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年亡容,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗤疯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡萍倡,死狀恐怖身弊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情列敲,我是刑警寧澤阱佛,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站戴而,受9級特大地震影響凑术,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜所意,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一淮逊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扶踊,春花似錦泄鹏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至分井,卻和暖如春车猬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尺锚。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工珠闰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瘫辩。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓伏嗜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伐厌。 傳聞我的和親對象是個殘疾皇子阅仔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 今天女兒學(xué)校要表演,早上七點的時候趕緊往回家趕了弧械。七點半匆匆忙忙吃了腸粉就送她去了。 中午表演完因為寶爸下午要上班...
    Ada左岸閱讀 144評論 0 0
  • 我平時叫在嘴上最多的是爸空民,手機聯(lián)系人上標(biāo)著老爸刃唐,微信里備注了芭比羞迷,寫到這時更愿意在心底稱呼父親,這么多的稱呼...
    梨花心事閱讀 310評論 0 3
  • 這幾天有意疏遠(yuǎn)哥哥画饥。今天早上道早安時衔瓮,哥哥用力的看著我的眼睛,我還是躲開了抖甘。后來他外出辦公热鞍,嘟了一下我的腰。前天還...
    哈姆Y特公主閱讀 107評論 0 0
  • 初次接觸到這個題目時衔彻,是在基礎(chǔ)寫作課上薇宠,老師給我們推薦了這位天才作家的散文,至今想不起來推薦理由艰额,滿腦子想的是一位...
    真射手偽文藝閱讀 2,026評論 0 2