有兩種實現方式,
原文出處: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) {
}
});
}兩種方式對比,個人覺得自定義體驗更好,動畫更簡單