1. 程式人生 > >Android自定義View實現水波紋效果

Android自定義View實現水波紋效果

本篇博文介紹一個Android自定義View的案例,後續博文會接下自定義View的相關流程和繪製原理。通過自定義控制元件實現。觸控式螢幕幕實現水波紋效果。實現步驟第1步.自定義MyWave繼承Viewpublic class MyWave extends View {}第2步.重寫帶兩個引數的構造方法public MyWave(Context context, AttributeSet attrs) {super(context, attrs);wList = new ArrayList<MyWave.Wave>();}第3步.重寫onDraw方法,在onDraw方法里根據水波紋集合mList,利用canvas.drawCircle方法繪製水波紋。在drawCircle方法中分別傳入水波紋的橫座標,縱座標,半徑和畫筆,其中畫筆包括要繪製的水波紋寬度和畫筆的顏色。這4個屬性封裝在Wave類中.onDraw方法每執行一次,都會繪製每一時刻的水波紋狀態。@Override
protected void onDraw(Canvas canvas) {for (int i = 0; i < wList.size(); i++) {Wave wave = wList.get(i);canvas.drawCircle(wave.pointX, wave.pointY, wave.radius, wave.paint);}}/*** 定義一個水波浪* @author afu*/private class Wave {//圓心int pointX;int pointY;//畫筆Paint paint;//半徑int radius;}第4步.重寫onTouchEvent方法,對觸控事件進行監聽,監聽MotionEvent.ACTION_MOVE事件,根據手指觸控的位置,新增水波紋到mList集合中@Override
public boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE://圓心int x = (int) event.getX();int y = (int) event.getY();addPoint(x,y);break;default:break;}return true;}第5步.在addPoint方法中,首先判斷是否第一次新增水波紋,若是第一次新增,則通過Handler啟動繪製動畫。若不是第一次,則取出最後一次新增的水波紋,判斷手指到最後一個水波紋的距離是否大於臨界值,若大於臨界值則新增新的水波紋到mList集合中。否則不新增,避免同個位置出現兩個水波紋。/**
* 新增新的水波浪中心點* @param x* @param y*/private void addPoint(int x, int y) {if(wList.size() == 0){addPoint2List(x,y);/** 第一次啟動動畫*/isRunning = true;handler.sendEmptyMessage(0);}else{//取最後一個圓環Wave w = wList.get(wList.size()-1);if(Math.abs(w.pointX - x)>DIS_SOLP || Math.abs(w.pointY-y)>DIS_SOLP){addPoint2List(x,y);}};}第6步.在Handler中首先通過flushData方法中對水波紋集合資料進行更新,降低水波紋的透明度同時增加水波紋的半徑。當水波紋的透明度為0的時候順便將其中mList集合中移除,重新整理mList水波紋集合資料,再執行invalidate方法通知View回撥onDraw方法對介面進行繪製。這樣水波紋就會不斷變大且透明度不斷降低,最後消失。private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {//重新整理資料flushData();//重新整理頁面invalidate();//迴圈動畫if (isRunning) {handler.sendEmptyMessageDelayed(0, 50);}};};/*** 重新整理資料*/private void flushData() {for (int i = 0; i < wList.size(); i++) {Wave w = wList.get(i);//如果透明度為 0 從集合中刪除int alpha = w.paint.getAlpha();if(alpha == 0){wList.remove(i); //刪除i 以後,i的值應該再減1 否則會漏掉一個物件,不過,在此處影響不大,效果上看不出來。continue;}alpha-=5;if(alpha<5){alpha =0;}//降低透明度w.paint.setAlpha(alpha);//擴大半徑w.radius = w.radius+3;//設定半徑厚度w.paint.setStrokeWidth(w.radius/3);}/** 如果集合被清空,就停止重新整理動畫*/if(wList.size() == 0){isRunning = false;}}第7步.最後在Activity的佈局中新增MyWave即可<com.example.administrator.waveview.MyWaveandroid:layout_width="match_parent"android:layout_height="match_parent" />效果圖如下所示(其中閃綠屏是gif圖截圖軟體GifCam的問題,程式在手機上執行不會出現綠屏的):