先上图,看看接下来我要向大家介绍的是个什么东西,例如以下图:



接下来要介绍的就是怎样实现上述图中的波纹效果。这样的效果假设大家没有体验过的话,能够看看百度手机卫士或者360手机卫士,里面的按钮点击效果都是这样的,另外Android 5.0以上的版本号也出现了这样的效果。

不多说,以下聊聊详细的怎么实现。

首先大家看到的是三个button,水波纹的出现给我们的错觉是直接将波纹绘制在button上面的,可是这样能做到吗?首先button自己有background和src,假设把半透明的水波纹当作background或者src绘制到button上面,肯定是会损失button原有的样式的。可能有朋友猜想那就把水波纹绘制在屏幕上呗,恭喜这位朋友答对了。至少我是这么干的,详细思路就是,我们自己实现一个layout,在layout中捕捉事件,并对事件进行对应的处理,在down事件中寻找当前用户点击的是哪个view,找出view所在的矩形区域,将一个透明的圆环绘制到这个矩形区域,在up事件中,延时分发view的onclick事件。

1、自己实现一个layout:

2、重写layout的dispatchTouchEvent方法,在down事件中找出被点击的view。

    public View findTargetView(float x, float y, View anchorView) {
ArrayList<View> 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的事件延时分发。

本文就写到这里了。本文案例的实现同一时候也參考了http://m.blog.csdn.net/blog/singwhatiwanna/42614953。在此对博主表示感谢。

源代码下载连接:Android button点击水波纹效果

Android点击Button水波纹效果的更多相关文章

  1. android自定义控件(4)-自定义水波纹效果

    一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...

  2. Android 自定义view实现水波纹效果

    http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...

  3. Android特效专辑(十)——点击水波纹效果实现,逻辑清晰实现简单

    Android特效专辑(十)--点击水波纹效果实现,逻辑清晰实现简单 这次做的东西呢,和上篇有点类似,就是用比较简单的逻辑思路去实现一些比较好玩的特效,最近也是比较忙,所以博客更新的速度还得看时间去推 ...

  4. android 点击水波纹效果

    这里是重点,<ripple>是API21才有的新Tag,正是实现水波纹效果的; 其中<ripple android:color="#FF21272B" .... ...

  5. Android自己定义控件系列五:自己定义绚丽水波纹效果

    尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...

  6. Android自定义控件-Path之贝赛尔曲线和手势轨迹、水波纹效果

    从这篇开始,我将延续androidGraphics系列文章把图片相关的知识给大家讲完,这一篇先稍微进阶一下,给大家把<android Graphics(二):路径及文字>略去的quadTo ...

  7. 兼容Android的水波纹效果

    Android的水波纹效果只有高版本才有,我们希望自己的应用在低版本用低版本的阴影,高版本用水波纹,这怎么做呢?其实,只要分drawable和drawablev21两个文件夹就好了. 普通情况下的se ...

  8. Android 颜色渲染(七) RadialGradient 环形渲染实现水波纹效果

    利用环形渲染我们可以做到什么? 其实很多都是非常常见的,比如上一篇实现的帮帮糖效果, 彩色的热气球,比如这里要讲到的水波纹效果,或者也可以理解为扩散色渲染效果 首先看一下效果图: 轻触屏幕,即可看到对 ...

  9. 关于自定义view--实现自定义水波纹效果

    开发中的东西太多,怕自己忘记了,简单记录一下. 声明:此控件借鉴了大佬的想法,在此感谢大佬提供的支持,我只是把大佬的想法拿出来而已. ok,废话到此结束,看效果: 分析一下,我们可以看到,图中有两个圆 ...

随机推荐

  1. 888. Fair Candy Swap@python

    Alice and Bob have candy bars of different sizes: A[i] is the size of the i-th bar of candy that Ali ...

  2. 「 Luogu P2574 」 XOR的艺术——线段树

    # 解题思路 这题不难,但是原谅我一开始的傻逼想法,一会儿再给大家透露透露. 先说怎么做这题. 显然对于 $0$ 和 $1$ 来说,异或无非也就只有两种变化 异或了奇数次,$0$ 就会变成 $1$,$ ...

  3. 条款17:以独立语句将newed对象置入智能指针(Store newed objects in smart pointers in standalone statements)

    NOTE: 1.以独立语句将newed对象存储于智能指针内.如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏.

  4. 条款6:若不想使用编译器自动生成的函数,就该明确拒绝(Explicity disallow the use of compiler-generated functions you do not want)

    class uncopyable{ protected: uncopyable(){};                                                         ...

  5. Tomcat server.xml配置文件

    server.xml配置文件: <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to ...

  6. Python旅途——简单语法

    1. 前言 在我们对环境以及pycharm安装好之后,我们就可以开始我们的Python之旅了,那么,我们学习一门语言应该如何开始呢?就像我们学习汉语一样,从abcd这些拼音学起,而对于我们Python ...

  7. Python 文件操作(一)

    一.注意事项 A.能调用方法的一定是对象 B.文件的操作流程: 1. 打开文件,得到文件句柄并赋值给一个变量 2. 通过句柄对文件进行操作 3. 关闭文件 二.操作实现方法 '''文件名:小双双文件内 ...

  8. Android开发——程序锁的实现(可用于开发钓鱼登录界面)

    1. 程序锁原理 1.1 实现效果: 在用户打开一个应用时,若此应用是我们业务内的逻辑拦截目标,那就在开启应用之后,弹出一个输入密码的界面,输入密码正确则进入目标应用.若不输入直接按返回键,则直接返回 ...

  9. u-boot-2012.04.01移植笔记——支持NAND启动

    1.加入nand读写函数文件: 对于nand的读写我们需要特定的函数,之前写最小bootloader的时候曾写过nand.c文件,我们需要用到它.为了避免混淆,我们先将其改名为init.c,然后拷贝到 ...

  10. asp网页无法打开

    环境:Window 2003.IIS6.Framework1.1 .VS2003 一个WebForm项目里面包含一些asp网页  运行后发现asp页面无法访问 提示:无法找到该页 解决方案: 1. [ ...