首先看一下效果:
实现这个效果,其实需要分析一下有几个动画 。很明显一开始是一个小圆,慢慢的在外扩散,所以这里有两个动画,x轴缩放动画,y轴缩放动画。另外在扩散的过程中,圆的透明度也是在不断变化的,所以有一个透明度的动画。总结起来,有3个动画,如下:
- x轴动画,对应的属性是ScaleX
- y轴动画,对象的属性是ScaleY
- 透明度动画,对应的属性是Alpha(1-->0)
下面看代码如何实现。
1、自定义一个容器,继承于RelativeLayout。用于管理需要执行的几个水波纹,这里使用了4个水波纹
2、自定义水波纹,继承于View。
自定义容器类:添加4个水波纹
public class MyAnimationRelativeLayout extends RelativeLayout {
private float radius;
private float strokeWidth;
private int strokeColor;
private List<MyCircleView> mViewList;
private AnimatorSet animatorSet;
private boolean isRunning = false;
public MyAnimationRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.waterView);
radius = array.getDimension(R.styleable.waterView_radius,54);
strokeWidth = array.getDimension(R.styleable.waterView_strokeWidth,4);
strokeColor = array.getColor(R.styleable.waterView_waterColor,context.getResources().getColor(R.color.colorPrimary));
array.recycle();
initView();
}
public int getStrokeColor() {
return strokeColor;
}
public void setStrokeColor(int strokeColor) {
this.strokeColor = strokeColor;
}
public float getStrokeWidth() {
return strokeWidth;
}
public void setStrokeWidth(float strokeWidth) {
this.strokeWidth = strokeWidth;
}
private void initView(){
mViewList = new ArrayList<>();
animatorSet = new AnimatorSet();
List<Animator> animationList = new ArrayList<>();
LayoutParams lp = new LayoutParams((int)radius,(int)radius);
lp.addRule(CENTER_IN_PARENT);
int scaleFlag = 5;//缩放系数
int animTime = 3500;
int perTime = 3500/4;
for(int i=0;i<4;i++){
MyCircleView myCircleView = new MyCircleView(this);
addView(myCircleView,lp);
mViewList.add(myCircleView);
//设置x缩放动画
ObjectAnimator xScaleAnim = ObjectAnimator.ofFloat(myCircleView,"ScaleX",1,scaleFlag);
xScaleAnim.setDuration(animTime);
xScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
xScaleAnim.setRepeatMode(ValueAnimator.RESTART);
xScaleAnim.setStartDelay(perTime*i);
//设置y缩放动画
ObjectAnimator yScaleAnim = ObjectAnimator.ofFloat(myCircleView,"ScaleY",1,scaleFlag);
yScaleAnim.setDuration(animTime);
yScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
yScaleAnim.setRepeatMode(ValueAnimator.RESTART);
yScaleAnim.setStartDelay(perTime*i);
//设置透明度变化
ObjectAnimator aScaleAnim = ObjectAnimator.ofFloat(myCircleView,"Alpha",1,0);
aScaleAnim.setDuration(animTime);
aScaleAnim.setRepeatMode(ValueAnimator.RESTART);
aScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
aScaleAnim.setStartDelay(perTime*i);
animationList.add(xScaleAnim);
animationList.add(yScaleAnim);
animationList.add(aScaleAnim);
}
animatorSet.setDuration(animTime);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
animatorSet.playTogether(animationList);
}
public boolean isRunning() {
return isRunning;
}
/**
* 开始动画
*/
public void startAnim(){
if(!isRunning){
isRunning = true;
for (MyCircleView myCircleView : mViewList) {
myCircleView.setVisibility(VISIBLE);
}
animatorSet.start();
}
}
public void stopAnim(){
if(isRunning){
isRunning = false;
//倒叙一下, 从外往里面停止
Collections.reverse(mViewList);
for (MyCircleView myCircleView : mViewList) {
myCircleView.setVisibility(INVISIBLE);
}
animatorSet.end();
}
}
}
自定义属性文件attrs:可以设置水波纹颜色,半径
<declare-styleable name="waterView">
<attr name="radius" format="dimension"/>
<attr name="strokeWidth" format="dimension"/>
<attr name="waterColor" format="color"/>
</declare-styleable>
自定义水波纹:主要画一个圆
public class MyCircleView extends View {
private Paint mPaint;
private MyAnimationRelativeLayout myAnimationRelativeLayout;
public MyCircleView(MyAnimationRelativeLayout myAnimationRelativeLayout) {
this(myAnimationRelativeLayout.getContext(),null);
this.myAnimationRelativeLayout = myAnimationRelativeLayout;
setVisibility(INVISIBLE);//默认不可见
initPaint();
}
public MyCircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
private void initPaint(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(myAnimationRelativeLayout.getStrokeColor());
mPaint.setStrokeWidth(myAnimationRelativeLayout.getStrokeWidth());
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置半径
int radius = Math.min(canvas.getHeight()/2,canvas.getWidth()/2);
//中心点位置
canvas.drawCircle(radius,radius,radius-myAnimationRelativeLayout.getStrokeWidth(),mPaint);
}
}
这里就完成了主要的代码,需要注意的是在容器中我们添加了4个水波纹,并且为每个水波纹添加了3个动画,最后将这些动画放到动画集中执行。每个水波纹的执行时间间隔为这里的3500/4,并且每个动画是重复无限执行的。