有两种实现方式,
原文出处:https://blog.csdn.net/tx467220125/article/details/79853303#comments,他的文章是达到一定条件添加一个新的波纹,我修改之后,触发条件为点击手动触发添加。
1.自定义View
通过paint + canvas绘制
public class WaveView extends View {
private Paint mCenterPaint; //中心圆paint
private int mRadius = 0; //中心圆半径 默认0
private Paint mSpreadPaint; //扩散圆paint
private float centerX;//圆心x
private float centerY;//圆心y
private int mMaxRadius = 0; //最大圆半径,默认扩展到屏幕两边
private List<Integer> spreadRadius = new ArrayList<>();//扩散圆层级数,元素为扩散的距离
private List<Integer> alphas = new ArrayList<>();//对应每层圆的透明度
private int mAlphaScale = 3;
public WaveView(Context context) {
this(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// radius = (int) getResources().getDisplayMetrics().density * 50;
mMaxRadius = getResources().getDisplayMetrics().widthPixels / 2;
int centerColor = context.getResources().getColor(R.color.colorPrimaryDark);
int spreadColor = context.getResources().getColor(R.color.colorPrimaryDark);
mCenterPaint = new Paint();
mCenterPaint.setColor(centerColor);
mCenterPaint.setAntiAlias(true);
mSpreadPaint = new Paint();
mSpreadPaint.setAntiAlias(true);
mSpreadPaint.setAlpha(255);
mSpreadPaint.setColor(spreadColor);
}
/**
* 设置相关参数
*
* @param nradius 中心园半径,起始位置
* @param maxwidth 最大扩展距离
* @param alphaScale 每次透明度变化的大小
* @param centerColor 中心园颜色
* @param spreadColor 扩散颜色
*/
public void setparams(int nradius, int maxwidth, int alphaScale, int centerColor, int spreadColor) {
mRadius = nradius;
if (maxwidth < nradius) {
mMaxRadius = nradius;
} else {
mMaxRadius = maxwidth;
}
mAlphaScale = alphaScale;
mCenterPaint.setColor(centerColor);
mSpreadPaint.setColor(spreadColor);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w / 2;
centerY = h / 2;
}
public void click() {
if (alphas != null) {
alphas.add(255);
}
if (spreadRadius != null)
spreadRadius.add(0);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (spreadRadius.isEmpty()) {
return;
}
for (int i = 0; i < spreadRadius.size(); i++) {//一层一层绘制渐变扩散
int alpha = alphas.get(i);
mSpreadPaint.setAlpha(alpha);
int width = spreadRadius.get(i);
//绘制扩散的圆
canvas.drawCircle(centerX, centerY, mRadius + width, mSpreadPaint);
//每次扩散圆半径递增,圆透明度递减
if (alpha > 0) {
alpha = alpha - mAlphaScale > 0 ? alpha - mAlphaScale : 0;
alphas.set(i, alpha);
spreadRadius.set(i, width + (mMaxRadius - mRadius) * mAlphaScale / 255);
}
}
//当最外层扩散圆半径达到最大半径时添加新扩散圆
if (spreadRadius.get(spreadRadius.size() - 1) >= mMaxRadius) {
//扩散到最大 移除最外圈
alphas.remove(0);
spreadRadius.remove(0);
}
invalidate();
// postInvalidateDelayed(10);//不能延时 不然会有卡顿感
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
click();
}
return super.onTouchEvent(event);
}
}
这个是自定义view,添加到布局中,点击即可看见水波纹
2.动画
这里采用动态添加和动画集合的方式实现
private RelativeLayout layoutAnimation;
private float mAnimationScaleSize = 0;
/**
* 启动一个水波纹动画
*/
private void startAnimation() {
int nWidth = (int) getResources().getDisplayMetrics().density * 50;//动画view初始大小
if (mAnimationScaleSize == 0) {
//根据宽高,计算缩放的比例
int max = layoutAnimation.getWidth() < layoutAnimation.getHeight() ?
layoutAnimation.getHeight() : layoutAnimation.getWidth();
mAnimationScaleSize = max * 1.0f / nWidth;
}
final ImageView nImg = new ImageView(WaveActivity.this);
layoutAnimation.addView(nImg);//动态添加
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(nWidth, nWidth);
param.addRule(RelativeLayout.CENTER_IN_PARENT);//居中
nImg.setImageResource(R.drawable.wave_bg);//背景
nImg.setLayoutParams(param);
AnimationSet set = new AnimationSet(true);
ScaleAnimation sAni = new ScaleAnimation(1.0f, mAnimationScaleSize, 1.0f, mAnimationScaleSize,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f);//缩放动画
AlphaAnimation aAni = new AlphaAnimation(1.0f, 0.0f);//透明度动画
sAni.setDuration(1000);
set.setDuration(1000);
set.addAnimation(sAni);
set.addAnimation(aAni);
nImg.startAnimation(set);//开启动画
set.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
layoutAnimation.post(new Runnable() {
@Override
public void run() {
nImg.clearAnimation();
layoutAnimation.removeView(nImg);
//动画完成之后 清除,移除
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}两种方式对比,个人觉得自定义体验更好,动画更简单