Android实现点击Button产生水波纹效果

2019-12-10 19:27:22丽君

重写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();
    }
  }

在分发绘制事件中大家可以看到,波纹是一段一段的绘制,形如下图: 

Android实现点击Button产生水波纹效果

而这一段段的波纹正是通过绘制一个个的圆环实现的,所以在没绘制完毕一个圆环的时候,都需要延时重新绘制下一个圆环。 
通过上面波纹效果基本上完成了,但是按钮是有点击事件的,像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);// 分发
      }
    }
  }