Files
qianyanAndroid/app/src/main/java/com/xuebiping/bolizhuzi/utils/WaveView.java
2026-03-17 20:24:06 +08:00

308 lines
9.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.xuebiping.bolizhuzi.utils;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 水波纹扩散效果
* https://github.com/hackware1993/WaveView
*/
public class WaveView extends View {
private float mInitialRadius; // 初始波纹半径
private float mMaxRadius; // 最大波纹半径
private long mDuration = 3000; // 一个波纹从创建到消失的持续时间
private int mSpeed = 1000; // 波纹的创建速度每500ms创建一个
private float mMaxRadiusRate = 1f;//0.85f;
private boolean mMaxRadiusSet;
private boolean mIsRunning;
private long mLastCreateTime;
private List<Circle> mCircleList = new ArrayList<Circle>();
private Runnable mCreateCircle = new Runnable() {
@Override
public void run() {
if (mIsRunning) {
newCircle();
postDelayed(mCreateCircle, mSpeed);
}
}
};
private Interpolator mInterpolator = new LinearInterpolator();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public WaveView(Context context) {
super(context);
}
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setStyle(Paint.Style style) {
mPaint.setStyle(style);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (!mMaxRadiusSet) {
mMaxRadius = Math.min(w, h) * mMaxRadiusRate / 2.0f;
}
}
public void setMaxRadiusRate(float maxRadiusRate) {
mMaxRadiusRate = maxRadiusRate;
}
public void setColor(int color) {
mPaint.setColor(color);
}
/**
* 开始
*/
public void start() {
if (!mIsRunning) {
mIsRunning = true;
mCreateCircle.run();
}
}
/**
* 缓慢停止
*/
public void stop() {
mIsRunning = false;
}
/**
* 立即停止
*/
public void stopImmediately() {
mIsRunning = false;
mCircleList.clear();
invalidate();
}
protected void onDraw(Canvas canvas) {
Iterator<Circle> iterator = mCircleList.iterator();
while (iterator.hasNext()) {
Circle circle = iterator.next();
float radius = circle.getCurrentRadius();
if (System.currentTimeMillis() - circle.mCreateTime < mDuration) {
mPaint.setAlpha(circle.getAlpha());
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
} else {
iterator.remove();
}
}
if (mCircleList.size() > 0) {
postInvalidateDelayed(10);
}
}
public void setInitialRadius(float radius) {
mInitialRadius = radius;
}
public void setDuration(long duration) {
mDuration = duration;
}
public void setMaxRadius(float maxRadius) {
mMaxRadius = maxRadius;
mMaxRadiusSet = true;
}
public void setSpeed(int speed) {
mSpeed = speed;
}
private void newCircle() {
long currentTime = System.currentTimeMillis();
if (currentTime - mLastCreateTime < mSpeed) {
return;
}
Circle circle = new Circle();
mCircleList.add(circle);
invalidate();
mLastCreateTime = currentTime;
}
private class Circle {
private long mCreateTime;
Circle() {
mCreateTime = System.currentTimeMillis();
}
int getAlpha() {
float percent = (getCurrentRadius() - mInitialRadius) / (mMaxRadius - mInitialRadius);
return (int) ((55 - mInterpolator.getInterpolation(percent) * 46));
//Log.i("透明度",""+mInterpolator.getInterpolation(percent));
//return (int) ((255*0.08)*mInterpolator.getInterpolation(percent));
}
float getCurrentRadius() {
float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius);
}
}
public void setInterpolator(Interpolator interpolator) {
mInterpolator = interpolator;
if (mInterpolator == null) {
mInterpolator = new LinearInterpolator();
}
}
/*private Context mContext;
private int centerRadius;
private int maxRadius;
private int waveWidth;
private long waveIntervalTime = 500;
private long waveDuration = 1500;
private boolean running = false;
private List<Wave> waveList = new ArrayList<>();
private Paint paint = new Paint();
private int centerColor;
public WaveView(Context context) {
this(context,null);
}
public WaveView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaveView,defStyleAttr,0);
centerColor = typedArray.getColor(
R.styleable.WaveView_center_color,
ContextCompat.getColor(context, R.color.mainTextColor)
);
centerRadius = (int) typedArray.getDimension(R.styleable.WaveView_center_radius, 4);
maxRadius = (int) typedArray.getDimension(R.styleable.WaveView_max_radius, 14f);
waveWidth = (int) typedArray.getDimension(R.styleable.WaveView_wave_width, 1.0f);
waveIntervalTime = typedArray.getInt(R.styleable.WaveView_wave_interval_time, 500);
waveDuration = typedArray.getInt(R.styleable.WaveView_wave_duration, 1500);
paint.setColor(centerColor);
typedArray.recycle();
}
public void setWaveStart(boolean waveStart) {
if (waveStart) {
if (!running) {
running = true;
waveList.add(new Wave());
}
} else {
running = false;
for (Wave wave: waveList) {
wave.cancelAnimation();
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int radius = (Math.min(w,h)/2);
if (radius < maxRadius) {
maxRadius = radius;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Wave wave: waveList) {
paint.setAlpha(wave.getAlpha());
paint.setStrokeWidth(waveWidth);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getWidth() >> 1, (getHeight() >> 1), wave.getCurrentRadius(), paint);
}
if (waveList.size() > 0) {
paint.setAlpha(255);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() >> 1, getHeight() >> 1, centerRadius, paint);
}
}
public class Wave {
private boolean hasCreateNewWave = false;
private ValueAnimator createWaveAnimation = ObjectAnimator.ofFloat(this, "percent", 0f, 1.0f);
private Float percent =0f;
@SuppressLint("ObjectAnimatorBinding")
public void setPercent(Float percent) {
this.percent = percent;
if (running && percent >= waveIntervalTime / waveDuration && !hasCreateNewWave) {
Wave wave = new Wave();
wave.createWaveAnimation.setInterpolator(new LinearInterpolator());
wave.createWaveAnimation.setDuration(waveDuration);
wave.createWaveAnimation.start();
wave.createWaveAnimation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (running) {
waveList.remove(Wave.this);
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
waveList.add(wave);
hasCreateNewWave = true;
}
invalidate();
}
public Float getPercent() {
return percent;
}
public void cancelAnimation() {
createWaveAnimation.cancel();
}
public int getAlpha() {
return (int) (255 * (1 - percent));
}
public float getCurrentRadius() {
return centerRadius + percent * (maxRadius - centerRadius);
}
}*/
}