Android点击Button水波纹效果
先上图,看看接下来我要向大家介绍的是个什么东西,例如以下图:
接下来要介绍的就是怎样实现上述图中的波纹效果。这样的效果假设大家没有体验过的话,能够看看百度手机卫士或者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水波纹效果的更多相关文章
- android自定义控件(4)-自定义水波纹效果
一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...
- Android 自定义view实现水波纹效果
http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...
- Android特效专辑(十)——点击水波纹效果实现,逻辑清晰实现简单
Android特效专辑(十)--点击水波纹效果实现,逻辑清晰实现简单 这次做的东西呢,和上篇有点类似,就是用比较简单的逻辑思路去实现一些比较好玩的特效,最近也是比较忙,所以博客更新的速度还得看时间去推 ...
- android 点击水波纹效果
这里是重点,<ripple>是API21才有的新Tag,正是实现水波纹效果的; 其中<ripple android:color="#FF21272B" .... ...
- Android自己定义控件系列五:自己定义绚丽水波纹效果
尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...
- Android自定义控件-Path之贝赛尔曲线和手势轨迹、水波纹效果
从这篇开始,我将延续androidGraphics系列文章把图片相关的知识给大家讲完,这一篇先稍微进阶一下,给大家把<android Graphics(二):路径及文字>略去的quadTo ...
- 兼容Android的水波纹效果
Android的水波纹效果只有高版本才有,我们希望自己的应用在低版本用低版本的阴影,高版本用水波纹,这怎么做呢?其实,只要分drawable和drawablev21两个文件夹就好了. 普通情况下的se ...
- Android 颜色渲染(七) RadialGradient 环形渲染实现水波纹效果
利用环形渲染我们可以做到什么? 其实很多都是非常常见的,比如上一篇实现的帮帮糖效果, 彩色的热气球,比如这里要讲到的水波纹效果,或者也可以理解为扩散色渲染效果 首先看一下效果图: 轻触屏幕,即可看到对 ...
- 关于自定义view--实现自定义水波纹效果
开发中的东西太多,怕自己忘记了,简单记录一下. 声明:此控件借鉴了大佬的想法,在此感谢大佬提供的支持,我只是把大佬的想法拿出来而已. ok,废话到此结束,看效果: 分析一下,我们可以看到,图中有两个圆 ...
随机推荐
- lspci详解分析
lspci详解分析 一.PCI简介 PCI是一种外设总线规范.我们先来看一下什么是总线:总线是一种传输信号的路径或信道.典型情况是,总线是连接于一个或多个导体的电气连线,总 线上连接的所有设备可在同一 ...
- ES6 第一章 let和const命令 具体参照http://es6.ruanyifeng.com
1.let类似于var用用来定义变量 1)let没有预解析,不存在变量提升 // var 的情况 console.log(foo); // 输出undefined var foo = 2; // le ...
- 弹跳加载动画特效Bouncing loader
一款非常常用的css 加载动画,这款CSS3 Loading动画主要由几个小球通过规律的上下跳动,渐隐渐显而成,效果十分生动.流畅.兼容IE8以上,尤其适合在移动端中使用,基本代替了图片实现加载的效果 ...
- Ahoi2014&Jsoi2014 支线剧情
题目描述 题解: 每条边至少经过一次,说明经过下界为$1$. 然后套有源汇上下界最小费用可行流板子. 口胡一下. 此类问题的建图通式为: 1.假设原来的边流量上下界为$[l,r]$,那么在新图中建流量 ...
- [CF] 474 F. Ant colony
区间重复不会影响GCD,ST表当然是支持的啦,常数这么小. 学到了三个东西: 1.lower_bound返回的是大于等于的位置,要判是否不存在(end())和是否超出所求[x,y]范围. 2.ST表更 ...
- 条款4:确定对象被使用前已被初始化(Make sure that objects are initialized before they're used)
其实 无论学何种语言 ,还是觉得要养成先声明后使用,先初始化再使用. 1.永远在使用对象之前先将其初始化. 内置类型: 必须手工完成. 内置类型以外的:使用构造函数完成.确保每一个构造函数都将对象的一 ...
- Farthest Nodes in a Tree (求树的直径)
题目链接,密码:hpu Description Given a tree (a connected graph with no cycles), you have to find the farthe ...
- Python+selenium(Autolt实现上传)
AutoIt是一个使用类似BASIC脚本语言的免费软件,被设计用来进行Windows GUI的自动化测试.它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现自动化任务. 此次小编介绍的是利用Auto ...
- python re 正则提取中文
需求: 提取文本中的中文和数字字母(大小写都要),即相当于删除所有标点符号. 其中new是原字符串 news = re.findall(r'[\u4e00-\u9fa5a-zA-Z0-9]',new)
- URAL 1277 Cops and Thieves
Cops and Thieves Time Limit: 1000ms Memory Limit: 16384KB This problem will be judged on Ural. Origi ...