Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android點擊Button水波紋效果

Android點擊Button水波紋效果

編輯:關於Android編程

先上圖,看看接下來我要向大家介紹的是個什麼東西,如下圖:
這裡寫圖片描述vcLwo7/K18/IYnV0dG9u19S8utPQYmFja2dyb3VuZLrNc3Jjo6zI57n7sNGw6824w/e1xMuusqjOxrWx1/diYWNrZ3JvdW5ku/LV33NyY7vm1sa1vWJ1dHRvbsnPw+ajrL/PtqjKx7vhy/DKp2J1dHRvbtSt09C1xNH5yr21xKGjv8nE3NPQxfPT0bLCz+vEx77NsNHLrrKozsa75tbG1NrGwcS7yc/fwqOsuafPstXizrvF89PRtPC21MHLo6zWwcnZztLKx9Xiw7S4ybXEo6y+38zly7zCt77NysejrM7Sw8fX1Ly6yrXP1tK7uPZsYXlvdXSjrNTabGF5b3V01tCytte9ysK8/qOssqK21MrCvP69+NDQz+DTprXEtKbA7aOs1Npkb3duysK8/tbQ0bDV0rWxx7DTw7unteO797XEysfExLj2dmlld6Os1dKz9nZpZXfL+dTatcS+2NDOx/jT8qOsvavSu7j2zbjD97XE1LK7t7vm1sa1vdXiuPa+2NDOx/jT8qOs1Np1cMrCvP7W0KOs0dPKsbfWt6J2aWV3tcRvbmNsaWNrysK8/qGjPGJyIC8+DQoxoaLX1Ly6yrXP1tK7uPZsYXlvdXSjujxiciAvPg0KMqGi1tjQtGxheW91dLXEZGlzcGF0Y2hUb3VjaEV2ZW50t723qKOs1Npkb3duysK8/tbQ1dKz9rG7teO797XEdmlld6GjPC9wPg0KPHByZSBjbGFzcz0="brush:java;"> public View findTargetView(float x, float y, View anchorView) { ArrayList touchablesView = anchorView.getTouchables(); View targetView = null; for (View child : touchablesView) { RectF rectF = getViewRectF(child); if (rectF.contains(x, y) && child.isClickable()) { // 這說明被點擊的view找到了 targetView = child; break; } } return targetView; }

接著找出view所在的矩形區域,因為要將波紋繪制到該區域:

    public RectF getViewRectF(View view) {
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int childLeft = location[0];
        int childTop = location[1];
        int childRight = childLeft + view.getMeasuredWidth();
        int childBottom = childTop + view.getMeasuredHeight();
        return new RectF(childLeft, childTop, childRight, childBottom);
    }

矩形區域找到之後,這個區域就是我們要繪制的博波紋所在地,上面也說過了,波紋其實就是圓環,繪制圓的畫是需要知道圓心坐標和圓的半徑,圓心坐標肯定就是down時候的x和y了,但是半徑怎麼計算合適?大家看到上面的圖知道如果view的寬度大於高度,點擊view的左下角或者右下角,那麼半徑基本上就是等於view的寬度,點擊view的上部或者下部分,半徑就是在0和view的高度之間,具體的計算方式看下圖:
這裡寫圖片描述
那麼根據上圖,半徑的計算方式就應該是:

    float left = circleCenterX - targetTouchRectF.left;
    float right = targetTouchRectF.right - circleCenterX;
    float top = circleCenterY - targetTouchRectF.top;
    float bottom = targetTouchRectF.bottom - circleCenterY;
    // 計算出最大的值則為半徑
    rawRadius = Math.max(bottom, Math.max(Math.max(left, right), top));

半徑算出來了,雖說圓心就是down時的x和y,但是有個地方還是需要注意的,在繪制圓環的時候提供的圓心坐標的x和y是在本文中是相對於layout的,所以在計算y的時候是需要進行一定處理的:

    /**
     * 獲取圓環的中心坐標
     */
    public float[] getCircleCenterPostion(float x,float y){
        int[] location = new int[2];
        float[] mDownPositon = new float[2];
        getLocationOnScreen(location );
        mDownPositon[0] = x;
        mDownPositon[1] = y -location[1];
        return mDownPositon;
    }

圓心坐標和半徑都計算好了,記下來就可以繪制圓形波紋了,那麼在哪裡繪制這個波紋比較合適呢?有朋友立馬就說肯定是在onDraw方法裡面繪制了,那麼恭喜你在我看來你是答錯了,我們的layout中是很有很多childview的,而layout是個viewGroup,viewGroup在繪制的時候,是先繪制自身的背景,再繪制自身,再繪制childview,如果在onDraw中繪制波紋,也就意味者後面繪制出來的childView會將我們的波紋遮蓋,所以我們就應該等到childview繪制完畢後再來繪制波紋,這樣可以保證childview在最頂層。
重寫dispatchDraw方法:

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        /**
         * 繪制完子元素後開始繪制波紋
         */
        if (mTargetTouchView != null) {
            RectF clipRectF = clipRectF(mTargetTouchView);
            canvas.save();
            // 為了不讓繪制的圓環超出所要繪制的范圍
            canvas.clipRect(clipRectF);
            if(drawedRadius < rawRadius){
                drawedRadius += rawRadius / drawingRadiusDegrees;
                canvas.drawCircle(mDownPositon[0], mDownPositon[1], drawedRadius, mHalfTransPaint);
                postInvalidateDelayed(INVALID_DURATION);
            }else{
                canvas.drawCircle(mDownPositon[0], mDownPositon[1], rawRadius, mTransPaint);
                post(delayedRunnable);
            }
            canvas.restore();
        }
    }

在分發繪制事件中大家可以看到,波紋是一段一段的繪制,形如下圖:
這裡寫圖片描述
而這一段段的波紋正是通過繪制一個個的圓環實現的,所以在沒繪制完畢一個圓環的時候,都需要延時重新繪制下一個圓環。
通過上面波紋效果基本上完成了,但是按鈕是有點擊事件的,像360手機衛士或者百度手機衛士等都是等波紋效果播放完畢後才會響應點擊事件,所以我們這裡也要對這個點擊事件進行延時響應。
在up事件中,記錄此次事件的event,並且返回true,表示消費此次的事件,然後再圓環繪制完畢後,再利用找到的view去分發這個event:

    if (ev.getAction() == MotionEvent.ACTION_UP) {
            // 需要讓波紋繪制完畢後再執行在up中執行的方法
//          if(drawedRadius==0){
//              return false;
//          }
//          long totalTime = (long) (INVALID_DURATION * (drawingRadiusDegrees+5));
//          // 離波紋結束的時間
//          long time = (long) (totalTime - drawedRadius*totalTime / rawRadius);
            delayedRunnable.event = ev;
            return true;
    }

    class postUpEventDelayed implements Runnable{
        private MotionEvent event;
        @Override
        public void run() {
            if(mTargetTouchView!=null && mTargetTouchView.isClickable()
                    && event!=null){
                mTargetTouchView.dispatchTouchEvent(event);// 分發
            }
        }
    }

在dispatchDraw方法中,判斷如果繪制完畢就post(delayedRunnable);執行childView的事件延時分發。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved