效果:

1.编写attrs文件

<?xml version="1.0" encoding="utf-8"?>
<resources><!--扩散圆颜色--><attr name="diffuse_color" format="color"/><!--中心圆颜色--><attr name="diffuse_coreColor" format="color"/><!--中心圆图片--><attr name="diffuse_coreImage" format="reference"/><!--中心圆半径--><attr name="diffuse_coreRadius" format="float"/><!--扩散圆宽度,值越小越宽--><attr name="diffuse_width" format="integer"/><!--最大扩散宽度--><attr name="diffuse_maxWidth" format="integer"/><!--扩散速度,值越大越快--><attr name="diffuse_speed" format="integer"/><declare-styleable name="DiffuseView"><attr name="diffuse_color"/><attr name="diffuse_coreColor"/><attr name="diffuse_coreImage"/><attr name="diffuse_coreRadius"/><attr name="diffuse_width"/><attr name="diffuse_maxWidth"/><attr name="diffuse_speed"/></declare-styleable></resources>

2.实现自定义view

package com.skyworth.car.rulerdemo;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;import java.util.ArrayList;
import java.util.List;/*** @Author: david.lvfujiang* @Date: 2019/12/12* @Describe:*/
public class DiffuseView extends View {/** 扩散圆圈颜色 */private int mColor = getResources().getColor(R.color.colorAccent);/** 圆圈中心颜色 */private int mCoreColor = getResources().getColor(R.color.colorPrimary);/** 中心圆半径 */private float mCoreRadius = 50;/** 扩散圆宽度 */private int mDiffuseWidth = 3;/** 最大宽度 */private Integer mMaxWidth = 500;/** 扩散速度 */private int mDiffuseSpeed = 5;/** 是否正在扩散中 */private boolean mIsDiffuse = false;// 透明度集合private List<Integer> mAlphas = new ArrayList<>();// 扩散圆半径集合private List<Integer> mWidths = new ArrayList<>();private Paint mPaint;public DiffuseView(Context context) {this(context, null);}public DiffuseView(Context context, AttributeSet attrs) {this(context, attrs, -1);}public DiffuseView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiffuseView, defStyleAttr, 0);mColor = a.getColor(R.styleable.DiffuseView_diffuse_color, mColor);mCoreColor = a.getColor(R.styleable.DiffuseView_diffuse_coreColor, mCoreColor);mCoreRadius = a.getFloat(R.styleable.DiffuseView_diffuse_coreRadius, mCoreRadius);mDiffuseWidth = a.getInt(R.styleable.DiffuseView_diffuse_width, mDiffuseWidth);mMaxWidth = a.getInt(R.styleable.DiffuseView_diffuse_maxWidth, mMaxWidth);mDiffuseSpeed = a.getInt(R.styleable.DiffuseView_diffuse_speed, mDiffuseSpeed);a.recycle();}private void init() {mPaint = new Paint();mPaint.setAntiAlias(true);mAlphas.add(255);mWidths.add(0);}@Overridepublic void invalidate() {if(hasWindowFocus()){super.invalidate();}}@Overridepublic void onWindowFocusChanged(boolean hasWindowFocus) {super.onWindowFocusChanged(hasWindowFocus);if(hasWindowFocus){invalidate();}}@Overridepublic void onDraw(Canvas canvas) {// 绘制扩散圆mPaint.setColor(mColor);for (int i = 0; i < mAlphas.size(); i ++) {// 设置透明度Integer alpha = mAlphas.get(i);mPaint.setAlpha(alpha);// 绘制扩散圆Integer width = mWidths.get(i);canvas.drawCircle(getWidth() / 2, getHeight() / 2,   width, mPaint);if(alpha > 0 && width < mMaxWidth){mAlphas.set(i, alpha - 2> 0 ? alpha - 2 : 1);mWidths.set(i, width + mDiffuseSpeed);}}// 判断当扩散圆扩散到指定宽度时添加新扩散圆if (mWidths.get(mWidths.size() - 1) >= mMaxWidth / mDiffuseWidth) {mAlphas.add(255);mWidths.add(60);}// 超过10个扩散圆,删除最外层if(mWidths.size() >= 15){mWidths.remove(0);mAlphas.remove(0);}// 绘制中心圆mPaint.setAlpha(255);mPaint.setColor(mCoreColor);canvas.drawCircle(getWidth() / 2, getHeight() / 2, mCoreRadius, mPaint);if(mIsDiffuse){invalidate();}}/*** 开始扩散*/public void start() {mIsDiffuse = true;invalidate();}/*** 停止扩散*/public void stop() {mIsDiffuse = false;mWidths.clear();mAlphas.clear();mAlphas.add(255);mWidths.add(0);invalidate();}/*** 是否扩散中*/public boolean isDiffuse(){return mIsDiffuse;}/*** 设置扩散圆颜色*/public void setColor(int colorId){mColor = colorId;}/*** 设置中心圆颜色*/public void setCoreColor(int colorId){mCoreColor = colorId;}/*** 设置中心圆半径*/public void setCoreRadius(int radius){mCoreRadius = radius;}/*** 设置扩散圆宽度(值越小宽度越大)*/public void setDiffuseWidth(int width){mDiffuseWidth = width;}/*** 设置最大宽度*/public void setMaxWidth(int maxWidth){mMaxWidth = maxWidth;}/*** 设置扩散速度,值越大速度越快*/public void setDiffuseSpeed(int speed){mDiffuseSpeed = speed;}
}

3.在activiy中调用

package com.skyworth.car.rulerdemo;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;public class Main2Activity extends AppCompatActivity {
DiffuseView waveView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);waveView = findViewById(R.id.diffuseView);waveView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {waveView.start();}});}
}<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:background="@color/black"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".Main2Activity"><com.skyworth.car.rulerdemo.DiffuseViewandroid:id="@+id/diffuseView"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true"app:diffuse_color="#91a9d7"app:diffuse_coreColor="@color/colorPrimaryDark"app:diffuse_coreImage="@mipmap/bluetooth"app:diffuse_coreRadius="60"app:diffuse_maxWidth="1000"/><ImageViewandroid:layout_width="60dp"android:layout_height="60dp"android:src="@mipmap/bluetooth"android:layout_centerInParent="true"android:id="@+id/center"/>
</RelativeLayout>