常见的水波纹效果:如下
然后换各种不同的颜色
我们给属性动画加一句动画的模式即可实现这样效果
实现思路
会画圆就能画波纹,会画波纹就能动
- 初始化一组数据包括每个波纹段的颜色,
- 对应的颜色初始化对应的画笔,
- 绘制静态的圆圈
工作完成了一大半,剩下的就是这个圆环动画的效果,就是让圆圈的半径从0到最大,ok 一个属性动画搞定,
- 初始化内容
//构造波纹属性
private void initTools() {
paints = new ArrayList<>();
circleRadiusList = new ArrayList<>();
waveColors = new ArrayList<>();
waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_20));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_40));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_60));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_80));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_100));
for (int paintColor : waveColors) {
Paint tempPaint = new Paint();
tempPaint.setColor(paintColor);
tempPaint.setAntiAlias(true);
tempPaint.setStrokeJoin(Paint.Join.ROUND);
tempPaint.setStrokeCap(Paint.Cap.ROUND);
tempPaint.setStyle(Paint.Style.FILL);
paints.add(tempPaint);
CircleRadiuEntity c = new CircleRadiuEntity();
circleRadiusList.add(c);
}
}
接下来就是出事后对应的属性动画
//这里只有一点需要注意的就是,每个index对应的属性动画启动的间隔是当前的角标 * 时间间隔
public void startWave() {
for (int i = 0; i < waveColors.size(); i++) {
ValueAnimator valueAnimatorC = ValueAnimator.ofFloat(0F, 1F);
final int finalI = i;
valueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//计算当前动画时间内,每个圆圈半径的变化
Float aFloat = Float.valueOf(animation.getAnimatedValue().toString());
circleRadiusList.get(finalI).setRadius((int) (maxRadius * aFloat));
invalidate();
}
});
valueAnimatorC.setRepeatCount(ValueAnimator.INFINITE);
valueAnimatorC.setRepeatMode(ValueAnimator.REVERSE);
valueAnimatorC.setDuration(UNIT_TIME * waveColors.size());
valueAnimatorC.setStartDelay(i * UNIT_TIME);
valueAnimatorC.start();
}
}
最后就是ondraw
//API非常简单就是根据我们计算的圆的半径绘制即可
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < paints.size(); i++) {
Paint currentCirclePaint = paints.get(i);
int currentCircleRadius = circleRadiusList.get(i).getRadius();
canvas.drawCircle(circelCenterPoint.x, circelCenterPoint.y, currentCircleRadius, currentCirclePaint);
}
}
代码非常简单就100行代码,完整的项目就不上传了,把完整的类放到最后,有兴趣的可以粘贴到项目中,
public class ClearCircleView extends View {
private static final int DEF_VIEW_SIZE = 200;
private static final int UNIT_TIME = 300;
private Point circelCenterPoint;
private int maxRadius;
private ArrayList<Integer> waveColors;
private List<Paint> paints;
private List<CircleRadiuEntity> circleRadiusList;
public ClearCircleView(Context context) {
this(context, null);
}
public ClearCircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ClearCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initTools();
}
private void initTools() {
paints = new ArrayList<>();
circleRadiusList = new ArrayList<>();
waveColors = new ArrayList<>();
waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_20));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_40));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_60));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_80));
waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_100));
// waveColors.add(ContextCompat.getColor(getContext(), R.color.colorAccent));
// waveColors.add(ContextCompat.getColor(getContext(), R.color.colorPrimary));
// waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_green_light));
// waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_orange_light));
// waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_red_light));
// waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_purple));
// waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));
for (int paintColor : waveColors) {
Paint tempPaint = new Paint();
tempPaint.setColor(paintColor);
tempPaint.setAntiAlias(true);
tempPaint.setStrokeJoin(Paint.Join.ROUND);
tempPaint.setStrokeCap(Paint.Cap.ROUND);
tempPaint.setStyle(Paint.Style.FILL);
paints.add(tempPaint);
CircleRadiuEntity c = new CircleRadiuEntity();
circleRadiusList.add(c);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
circelCenterPoint = new Point(w / 2, h / 2);
maxRadius = Math.min(w, h) / 2;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMeaure;
int heightMeaure;
if (widthMeasureMode == MeasureSpec.AT_MOST || widthMeasureMode == MeasureSpec.UNSPECIFIED) {
widthMeaure = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_VIEW_SIZE, getResources().getDisplayMetrics());
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeaure, MeasureSpec.EXACTLY);
}
if (heightMeasureMode == MeasureSpec.AT_MOST || heightMeasureMode == MeasureSpec.UNSPECIFIED) {
heightMeaure = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_VIEW_SIZE, getResources().getDisplayMetrics());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeaure, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < paints.size(); i++) {
Paint currentCirclePaint = paints.get(i);
int currentCircleRadius = circleRadiusList.get(i).getRadius();
canvas.drawCircle(circelCenterPoint.x, circelCenterPoint.y, currentCircleRadius, currentCirclePaint);
}
}
public void startWave() {
for (int i = 0; i < waveColors.size(); i++) {
ValueAnimator valueAnimatorC = ValueAnimator.ofFloat(0F, 1F);
final int finalI = i;
valueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float aFloat = Float.valueOf(animation.getAnimatedValue().toString());
circleRadiusList.get(finalI).setRadius((int) (maxRadius * aFloat));
invalidate();
}
});
valueAnimatorC.setRepeatCount(ValueAnimator.INFINITE);
valueAnimatorC.setRepeatMode(ValueAnimator.REVERSE);
valueAnimatorC.setDuration(UNIT_TIME * waveColors.size());
valueAnimatorC.setStartDelay(i * UNIT_TIME);
valueAnimatorC.start();
}
}
class CircleRadiuEntity {
int radius;
int getRadius() {
return radius;
}
void setRadius(int radius) {
this.radius = radius;
}
}
}