RippleEffect原理解析
2015-02-24 00:35
302 查看
闲来无事,看了看RippleEffect的具体实现过程,先将心得写下,与诸位共享…
RippleEffect的效果就是点击View,然后View上一个圆圈慢慢的变大,然后消失…
原效果:
我的Demo效果:
原理:重写View的
(1)定义变量:
(2)重写
(3)在构造函数中,我们需要初始化我们的画笔,用来刷新界面的Handler。
(4)想象一下,我们用手点击View的时候,点击的位置出现一个逐渐放大的圆,那么我们肯定就需要重写
(4-1)重写
(4-2)编写
这个函数最主要的作用,就是设置
(4-3)接下来就得编写我们最核心的函数
在onDraw函数中,做的最重要的事情就是
【源代码下载地址】
【本博将会持续不断的关注各种Android开源组件的核心原理,欢迎大家转载分享~不明白的地方直接评论回复即可】
RippleEffect的效果就是点击View,然后View上一个圆圈慢慢的变大,然后消失…
原效果:
我的Demo效果:
原理:重写View的
onDraw(Canvas canvas)方法,然后使用
canvas.drawCircle(x, y, currentRadius, paint),通过不断的改变currentRadius的值,使其从小到大的变化,来达到这么一种效果。
(1)定义变量:
/** * 圆从最小到最大,需要多长时间 */ private int DURATION = 2000; /** * 想要画的圆的最大半径 */ private float radiusMax = 0; /** * View的最大宽度 */ private int WIDTH; /** * View的最大高度 */ private int HEIGHT; /** * 记录手指点下去的x坐标 */ private float x; /** * 记录手指点下去的y坐标 */ private float y; /** * 对timer的放大系数 */ private int FRAME_RATE = 10; /** * 通过timer不停的timer++,达到让圆不断增大的效果 */ private int timer = 0; /** * Handler用来更新界面用的 */ private Handler canvasHandler; /** * 是否正在播放动画 */ private boolean animationRunning = false; /** * 画笔 */ private Paint paint; /** * 结合Handler用来刷新当前界面的任务 */ private final Runnable runnable = new Runnable() { @Override public void run() { invalidate(); } };
(2)重写
protected void onSizeChanged(int w, int h, int oldw, int oldh)得到我们View的高度和宽度。
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Log.d("K", "onSizeChanged,w:" + w + ", h: " + h); WIDTH = w; HEIGHT = h; }
(3)在构造函数中,我们需要初始化我们的画笔,用来刷新界面的Handler。
/** * 初始化画笔,Handler * @param context */ private void init(Context context){ paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL); paint.setColor(getResources().getColor(android.R.color.white)); canvasHandler = new Handler(); }
(4)想象一下,我们用手点击View的时候,点击的位置出现一个逐渐放大的圆,那么我们肯定就需要重写
public boolean onTouchEvent(MotionEvent event)方法,然后记录下我们点击的(x, y)坐标,然后以这个(x, y)位置为圆心,以适当半径画一个圆就OK。
(4-1)重写
onTouchEvent(MotionEvent event)方法,响应用户触屏事件。
@Override public boolean onTouchEvent(MotionEvent event) { animateRipple(event); return super.onTouchEvent(event); }
(4-2)编写
animateRipple函数,在没有播放动画的时候,播放动画,即画圆。
/** * 开始画圆 * @param event */ public void animateRipple(MotionEvent event){ //当前没有播放动画的时候,执行这些赋值操作 if(!animationRunning){ radiusMax = Math.max(WIDTH, HEIGHT); Log.d("K","radius:" + radiusMax); this.x = event.getX(); this.y = event.getY(); animationRunning = true; invalidate(); } }
这个函数最主要的作用,就是设置
animationRunning这个变量,用以标示当前是否正在播放动画。然后确定了我们当前想要画的圆的最大半径是手机宽度和高度的最大值。
(4-3)接下来就得编写我们最核心的函数
onDraw(Canvas canvas)了,
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(animationRunning){ if(DURATION <= timer * FRAME_RATE){ animationRunning = false; timer = 0; canvas.restore(); Log.d("K", "animation end."); return; }else{ //每隔FRAME_RATE刷新一下 canvasHandler.postDelayed(runnable, FRAME_RATE); } if(timer == 0){ canvas.save(); } float currentRadius = radiusMax * (((float) timer * FRAME_RATE) / DURATION); Log.d("K", "current radius:" + currentRadius); canvas.drawCircle(x, y, (currentRadius), paint); timer++; } }
在onDraw函数中,做的最重要的事情就是
canvas.drawCircle(x, y, (currentRadius), paint);,这个是我们的核心代码,就是这句代码呈现出来我们想画的圆。那么
currentRadius是靠什么来改变的呢?答案就是
timer变量,我们知道每调用一次
invalidate(),
onDraw函数就会被调用一次,所以我们可以在onDraw函数中通过不断的累加timer,来模拟半径的不断增加。
DURATION是总的时长,
FRAME_RATE相当于是对
timer的一个放大系数,
FRAME_RATE * timer必须大于
DURATION的时候,我们就
canvas.restore()恢复现场,回到没有画圆之前的场景,即圆消失。
【源代码下载地址】
【本博将会持续不断的关注各种Android开源组件的核心原理,欢迎大家转载分享~不明白的地方直接评论回复即可】
相关文章推荐
- yahoo,3721,baidu谁让你如此猖狂!解析流氓原理!
- 用WinRAR解析木马病毒的捆绑原理[多图]
- 网站验证码的技术原理和实例解析
- 谈谈scriptaculous动画效果库effect.js(原理和使用)
- Lucene原理解析
- 摘《谈谈scriptaculous动画效果库effect.js(原理和使用)》
- DDoS攻击原理解析
- 无盘原理和分类详细解析
- 深入解析php模板技术原理【一】
- Struts原理的解析与其实践指导大全 (1)
- 解析木马后门的原理
- SNIFF原理解析
- [导入]Ajax技术原理解析
- 实例解析蠕虫病毒的原理
- Tomcat中详细配置数据源及其原理解析
- DNS服务器工作原理完全解析
- 解析***后门的原理 把它扼杀在摇篮里
- 域名专题-DNS解析原理
- Mp3原理及文件格式解析
- OFDM信号发送接收原理解析