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



接下来要介绍的就是怎样实现上述图中的波纹效果。这样的效果假设大家没有体验过的话,能够看看百度手机卫士或者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. Hibernate-01 入门

    学习任务 Hibernate开发环境的搭建 使用Hibernate对单表进行增删改操作 使用Hibernate按照数据表主键查询 关于Hibernate 简介 Hibernate的创始人Gavin K ...

  2. encodeURI()与decodeURI()等转码方法

    只针对文本编码 encodeURI() 只针对文本解码 decodeURI()针对文本和特殊字符的编码  encodeURIComponent()针对文本和特殊字符的解码  decodeURIComp ...

  3. [JOYOI] 1096 数字组合

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  4. 剑指Offer(书):替换空格

    题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 分析:通常来说,这样的题有两种方式 ...

  5. 【01】在 Github 上编辑代码

    [01]在 Github 上编辑代码 当你使用 GitHub,看一些文件(任何的文本文件或者仓库),能看到一个顶部右侧有一个小铅笔图标.点击即可编辑文档. 完成后,按照提示点击「Propose fil ...

  6. Action中result的各种转发类型

    Action中result的各种转发类型 1,dispatcher:默认值 ,内部定向 <result>/WEB-INF/page/employeeAdd.jsp</result&g ...

  7. Python 和 Flask实现RESTful services

    使用Flask建立web services超级简单. 当然,也有很多Flask extensions可以帮助建立RESTful services,但是这个例实在太简单了,不需要使用任何扩展. 这个we ...

  8. POJ2926-Requirements,曼哈顿距离。去掉绝对值符号暴力枚举所有情况,神薙!

                                                         Requirements 好吧,这题我实在想不到什么优化的方法,看了看讨论区,顺便膜拜了一下大 ...

  9. [Go]链表的相关知识

    切片有着占用内存少喝创建便捷等特点,但它本质上还是数组.切片的一大好处是可以通过窗口快速地定位并获取或者修改底层数组中的元素.不过当删除切片中的元素的时候就没那么简单了.元素复制一般是免不了的,就算只 ...

  10. 【multimap的应用】D. Array Division

    http://codeforces.com/contest/808/problem/D #include<iostream> #include<cstdio> #include ...