Android开源组件原理解析

闲来无事,看了看RippleEffect的具体实现过程,先将心得写下,与诸位共享…

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() {() {invalidate();}};

(2)重写 protected void onSizeChanged(int w, int h, int oldw, int oldh) 得到我们View的高度和宽度。

(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*/(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) 方法,响应用户触屏事件。

(MotionEvent event) {animateRipple(event);return super.onTouchEvent(event);}

(4-2)编写 animateRipple 函数,在没有播放动画的时候,播放动画,即画圆。

/** * 开始画圆 * @param event */(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) 了,

(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开源组件的核心原理,,欢迎大家转载分享~不明白的地方直接评论回复即可】

伟人所达到并保持着的高处,并不是一飞就到的,

Android开源组件原理解析

相关文章:

你感兴趣的文章:

标签云: