Android实现涟漪动画

需求

因为开发launcher的桌面启动动画的时候,根据设计师的要求,需要实现一个涟漪的效果,具体效果如下:

然后动画的具体细节要求是这样的:

我Google搜索了一下涟漪效果,发现Github上有一些类似的开源库,但是发现大部分都是点击按钮然后开始出现涟漪效果,与自己要做的这个涟漪动画不太符合,所以在dwl的启发下,想着干脆自己实现一个算了,于是就尝试着自定义这个涟漪动画,最终实现的效果就和上面的是一样的,下面阐述一下实现原理

原理

首先我们将这个动画看成是一个圆环,圆环里面的小圆是一个空心的透明圆,外面是一个透明的大圆,draw圆环的原理很简单,就是在draw透明圆的基础上,将画笔paint的strokeWidth设置成外面的环的宽度

这里需要注意的是,事实上通过设置strokeWidth之后draw出来的外面大圆的半径并不是简单的内圆的半径加上圆环的宽度,而是内圆的半径+1/2圆环的宽度

如下图所示,红色的就是半径就是我们在draw圆环外面大圆的时候应该设置的半径,然后将笔宽strokeWidth设置为圆环的宽度即可:

实现

那么知道draw圆环的原理之后,下面就可以开始draw了,里面的小圆很简单:

1
canvas.drawCircle(centerX, centerY, mCircleRadius, mCirclePaint);

外面的大圆:

1
canvas.drawCircle(centerX, centerY, mCircleRadius + mRippleWidth / 2, mRipplePaint);

重点就是mRippleWidth这个变量,根据动画介绍可以,波纹的宽度是从0到mRippleWidth,那么根据上面我们说的外圆的半径为内圆的半径+1/2(圆环)波纹的宽度,所以大圆的半径是mCircleRadius+mRippleWidth/2

半径的变化规律知道了,只有半径的变化显然是不够的,为了达到波纹从0到mRippleWidth的效果,我们必须同步更改大圆画笔paint的strokeWidth的值,也就是画出圆环效果,strokeWidth的变化规律和波纹宽度是一样的,从0到mRippleWidth。ok,知道了半径和大圆画笔的变化规律,接下来就是按照规律去改变对应的值,然后刷新界面了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
ValueAnimator va = ValueAnimator.ofInt(0, sRippleWidth);
va.setDuration(RIPPLE_ANIM_DURATION * 2);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
mRippleWidth = value;
mRipplePaint.setStrokeWidth(value);
invalidate();
}
});
va.start();

在初始化代码片段中,我们将外面的大圆画笔paint的strokeWidth初始化为0,颜色初始化成波纹的颜色:

1
2
3
mRipplePaint.setStyle(Paint.Style.STROKE);
mRipplePaint.setStrokeWidth(0);
mRipplePaint.setARGB(127, 255, 255, 255);

然后根据动画的定义,我们逐渐地将画笔的宽度设置为从0到最终波纹宽度的每一个临时宽度,同时也将波纹变化过程中的的每一个临时宽度值赋值给mRippleWidth用来更新大圆的半径。然后调用invalidata()刷新界面,这样效果就出来了

当然还有一些细节,比如波纹宽度渐变的过程中,要伴随着alpha变化,同时要求波纹到指定时间后自动开始(这里是3000毫秒开始),都需要我们去实现,但这些不是主要难点了,相信大家都能搞定

就这样了,欢迎大家交流意见