android 實現水波紋效果(二) 優化篇
在我的上一篇文章中,初步介紹了一下水波紋的實現,確實也實現了,剛開始我表示很滿意啊,但是後來看了一下系統的實現效果,我開始發現有點不對勁;來對比一下:
這是優化前的效果
這是優化後的效果
區別看不出來?仔細看一下,系統的實現效果是不管點選到哪裡,兩側的陰影效果都會同時到達頂點,但是上一篇中實現的效果則不一樣,靠近那一側,就會先到達那一側;接下來就進行一下優化:
先分析 一下:
在繪製圓形的時候,肯定是以圓心開始向四周繪製,這樣,由於圓心固定在一點,那麼隨著半徑的增加,圓邊肯定先到達距離圓心較近的一側,而在上篇中,我是獲取down事件中觸控點作為圓心,然後不斷增加半徑,實現效果;ok!到這裡,問題就分析出來了;想要解決這個問題,最主要的就是解決圓心偏移的問題;
至於圓心偏移量的問題,我開始也想了很多種計算公式(汗,都怪當初沒學好小學數學啊..);後來也是在網上看到一個大神的解決方法;
- 兩側都到達View邊界的時候,由於是同時到達,這時候,圓心肯定在x軸的中點
- 這時候半徑就是繪製區域寬度的1/2
- 圓心的偏移量就是從down事件的觸控點到控制元件中心處
- 半徑的變化也就是從0到 width/2
接下來上程式碼放大招:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
a = System.currentTimeMillis();
//down事件中,開始繪製
isDraw = true;
currentRadio = 0;
//點選的位置,也是水波紋的圓心
int downX = (int) event.getRawX();
int downY = (int) event.getRawY();
centerX = downX;
centerY = downY;
//找到對應的子控制元件
targetView = findTargerView(downX, downY);
//如果沒有子控制元件被點選,就直接結束
if (targetView != null) {
//矯正繪製區域
clipRectf();
/***************在這裡我獲取了偏移量*************/
gapX = (centerX-(rectF.left+rectF.right)/2);
gapY = (centerY-(rectF.top+rectF.bottom)/2);
/***************半徑我也喪心病狂的改了**************************************/
radio = (int) Math.max(rectF.width(),rectF.height())/2;
centerOffsetX = (gapX*1.0 / (times));
//重新繪製
postInvalidate();
}
break;
default:
isDraw = false;
currentRadio = 0;
postInvalidate();
JLog.i((System.currentTimeMillis() - a) + "");
break;
}
return super.dispatchTouchEvent(event);
}
這段程式碼大致還是一樣的,只不過增加以一個圓心偏移量的計算,同時半徑也改了,由於在圓心到達View中點時候,半徑也剛好是這個繪製區域的一半,其實這個半徑不應該理解為最大半徑,而應該是在圓心到達View中點時候的半徑,這樣方便將圓心偏移和raido半徑變化同步,免得在圓心到達View中點時候,半徑還沒到達View兩側,這樣就比較尷尬了;
圓心偏移量和半徑得到之後,就可以開心的開始繪製了;
//在draw中被呼叫的方法,用來繪製子控制元件
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//子控制元件繪製完成後,開始繪製水波紋
canvas.save();
if (targetView == null) return;
if (isDraw) {
//計算圓心偏移量
if (currentRadio <= radio) {
centerX -= centerOffsetX;
// centerY-= centerOffsetY;
JLog.i(centerY+"");
}
//限制繪製區域
canvas.clipRect(rectF);
canvas.drawCircle((float) centerX,(float) centerY, (float)currentRadio, mPaint);
currentRadio += radio*1.00 / times;
postInvalidateDelayed((long) (time / times));
} else {
canvas.clipRect(rectF);
canvas.drawCircle((float)centerX, (float)centerY,(float) currentRadio, mPaint);
}
canvas.restore();
}
繪製過程增加了圓心偏移量,其他的基本也沒太多變化,但是有幾點需要注意:
- 在圓心到達View中點的時候,就不要再進行偏移了,可以節省點記憶體,同時也避免一些童鞋繪製半徑有最大值的時候發現水波紋呼呼的飄走了
圓心偏移量的百分比和水波紋半徑radio增加的百分比,一定要同步!!!這個必須要同步,否則圓心偏移量可能就白計算了
好了優化就到這裡了,當然我知道我沒進行y方向的偏移,這個就不要介意了,畢竟懶了一些
最後,這次程式碼裡我添加了兩個方法,一個是改變水波紋顏色,一個是設定水波紋繪製速度;這個控制元件當然有很多不完善的地方,比如我沒有通過屬性來設定顏色,繪製速度等 ,但是主要功能我已經實現了.需要其他功能的時候,就自己新增以下吧;
有什麼問題,可以評論裡一起討論;
還有:原始碼