人生只是一种体验,不必用来演绎完美。
效果图
View源码
package com.android.circlescalebar.view; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; import android.view.animation.LinearInterpolator; import androidx.annotation.NonNull; import com.android.circlescalebar.utils.DensityUtils; import java.util.ArrayList; import java.util.List; public final class WaveView extends View { private static final String TAG = "WaveView"; private int centerColor = Color.GREEN; private int centerRadius = DensityUtils.dp2px(1.0F); private int maxRadius = DensityUtils.dp2px(105.0F); private int waveIntervalTime= 500; private int waveDuration = 1500; private boolean running; private ListwaveList = new ArrayList();; private int waveWidth = DensityUtils.dp2px(1.0F); private Paint paint = new Paint(); public WaveView(Context context) { super(context); } public WaveView(Context context, AttributeSet attrs) { super(context, attrs); } public WaveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public void setWaveStart(boolean waveStart) { if (waveStart) { if (!running) { running = true; waveList.add(new Wave()); } } else { running = false; for (Wave wave : waveList) { wave.cancelAnimation(); } } } protected void onSizeChanged(int w, int h, int oldw, int oldh) { int radius = (int)((float)Math.min(w, h) / 2.0F); if (radius maxRadius = radius; } } protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(centerColor); for (Wave wave : waveList) { paint.setAlpha(wave.getAlpha()); paint.setStrokeWidth((float)this.waveWidth); paint.setStyle(Paint.Style.STROKE); canvas.drawCircle((float)(this.getWidth() / 2), (float)(this.getHeight() / 2), wave.getCurrentRadius(),paint); } if (this.waveList.size() > 0) { paint.setAlpha(255); paint.setStyle(Paint.Style.FILL); canvas.drawCircle((float)(this.getWidth() / 2), (float)(this.getHeight() / 2), (float)this.centerRadius,paint); } } public final class Wave { public boolean hasCreateNewWave; public final ValueAnimator createWaveAnimation; public float percent; // public final float getPercent() {// return percent; // } // // public final void setPercent(float value) {// // Log.d(TAG, "Wave: percent" + value); // percent = value; // if (running && value >= (float)waveIntervalTime / (float)waveDuration && !this.hasCreateNewWave) {// waveList.add(new Wave()); // hasCreateNewWave = true; // } // invalidate(); // } public void cancelAnimation() { createWaveAnimation.cancel(); } public int getAlpha() { return (int)((float)255 * ((float)1 - percent)); } public float getCurrentRadius() { return (float)centerRadius +percent * (float)(maxRadius - centerRadius); } public Wave() {// createWaveAnimation = ObjectAnimator.ofFloat(this, "percent", 0F, 1F); createWaveAnimation = ObjectAnimator.ofFloat(this, "alpha", 0F, 1F); createWaveAnimation.setInterpolator(new LinearInterpolator()); createWaveAnimation.setDuration(waveDuration); createWaveAnimation.start(); createWaveAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) { float animatedValue = (float) valueAnimator.getAnimatedValue(); percent = animatedValue; if (running && animatedValue >= (float)waveIntervalTime / (float)waveDuration && !hasCreateNewWave) { waveList.add(new Wave()); hasCreateNewWave = true; } invalidate(); } }); createWaveAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); waveList.remove(this); } }); } } }
工具类
package com.android.circlescalebar.utils; import android.content.res.Resources; public class DensityUtils { public float density; public DensityUtils() { density = Resources.getSystem().getDisplayMetrics().density; } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) * @param dpValue 虚拟像素 * @return 像素 */ public static int dp2px(float dpValue) { return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp * @param pxValue 像素 * @return 虚拟像素 */ public static float px2dp(int pxValue) { return (pxValue / Resources.getSystem().getDisplayMetrics().density); } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) * @param dpValue 虚拟像素 * @return 像素 */ public int dip2px(float dpValue) { return (int) (0.5f + dpValue * density); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp * @param pxValue 像素 * @return 虚拟像素 */ public float px2dip(int pxValue) { return (pxValue / density); } }
调用实现
waveView.setWaveStart(true);
布局