目录

Android-自定义蓝牙扫描动画多波浪扩散效果

目录

Android 自定义蓝牙扫描动画:多波浪扩散效果

这是一个用于 Android 的自定义 View,模拟蓝牙扫描时的多波浪扩散动画效果。每个波浪的半径逐渐增大,透明度逐渐降低,形成连续的波纹扩散效果。通过调整动画的延迟时间和时长,确保波浪之间的间隙较小,动画流畅且美观。 主要特性多波浪扩散: 支持多个圆圈(波浪)依次扩散,形成连续的波纹效果。 每个圆圈的半径逐渐增大,透明度逐渐降低。 间隙较小: 通过调整动画的延迟时间和动画时长,确保波浪之间的间隙较小。 自定义View: 使用 Canvas 和 Paint 实现自定义绘制。 使用 ValueAnimator 实现平滑的动画效果。 适用场景: 蓝牙扫描界面。 雷达扫描效果。 其他需要波纹扩散动画的场景。 使用方法:BluetoothScanView 添加到布局文件中。 在 Activity 中调用 startScan() 启动动画,调用 stopScan() 停止动画。 实现步骤 1 自定义View 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 java.util.ArrayList; import java.util.List; public class BluetoothScanView extends View { private Paint scanPaint; // 画笔 private List circles; // 存储圆圈的列表 private List animators; // 存储动画的列表 public BluetoothScanView(Context context) { super(context); init(); } public BluetoothScanView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public BluetoothScanView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { // 初始化画笔 scanPaint = new Paint(); scanPaint.setColor(Color.BLUE); // 设置颜色 scanPaint.setStyle(Paint.Style.STROKE); // 设置样式为描边 scanPaint.setStrokeWidth(5); // 设置描边宽度 scanPaint.setAntiAlias(true); // 抗锯齿 // 初始化圆圈和动画列表 circles = new ArrayList<>(); animators = new ArrayList<>(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = getWidth() / 2; // 中心点X坐标 int centerY = getHeight() / 2; // 中心点Y坐标 // 绘制所有圆圈 for (Circle circle : circles) { scanPaint.setAlpha(circle.alpha); // 设置透明度 canvas.drawCircle(centerX, centerY, circle.radius, scanPaint); } } public void startScan() { if (!animators.isEmpty()) { return; // 如果动画已经在运行,直接返回 } // 初始化3个圆圈 circles.clear(); circles.add(new Circle(0, 255)); // 第一个圆圈 circles.add(new Circle(0, 255)); // 第二个圆圈 circles.add(new Circle(0, 255)); // 第三个圆圈 // 为每个圆圈创建独立的动画 for (int i = 0; i < circles.size(); i++) { final Circle circle = circles.get(i); ValueAnimator animator = ValueAnimator.ofFloat(0, 1); // 动画范围从0到1 animator.setDuration(1500); // 动画时长1.5秒 animator.setStartDelay(i * 500); // 每个圆圈延迟0.5秒启动 animator.setRepeatCount(ValueAnimator.INFINITE); // 无限循环 animator.setRepeatMode(ValueAnimator.RESTART); // 重新开始 animator.addUpdateListener(animation -> { float progress = (float) animation.getAnimatedValue(); // 获取当前进度 circle.radius = (int) (progress * getWidth() / 2); // 更新半径 circle.alpha = (int) (255 * (1 - progress)); // 更新透明度 invalidate(); // 触发重绘 }); animators.add(animator); // 添加到动画列表 animator.start(); // 启动动画 } } public void stopScan() { // 停止所有动画 for (ValueAnimator animator : animators) { animator.cancel(); } animators.clear(); circles.clear(); invalidate(); // 刷新界面 } // 圆圈类,用于存储半径和透明度 private static class Circle { int radius; // 半径 int alpha; // 透明度 Circle(int radius, int alpha) { this.radius = radius; this.alpha = alpha; } } } 2 Activity import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private BluetoothScanView bluetoothScanView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化自定义View bluetoothScanView = findViewById(R.id.bluetoothScanView); // 确保View尺寸已确定后启动动画 bluetoothScanView.post(() -> { bluetoothScanView.startScan(); // 启动扫描动画 }); } @Override protected void onDestroy() { super.onDestroy(); bluetoothScanView.stopScan(); // 停止扫描动画 } } 3 布局文件 xml version=“1.0” encoding=“utf-8”?

运行效果 波浪扩散: 页面加载后,第一个圆圈开始扩散,随后第二个、第三个圆圈依次开始。 每个圆圈的半径逐渐增大,透明度逐渐降低。 间隙较小: 每个波浪之间的启动间隔为 500 毫秒,动画时长为 1500 毫秒,波浪之间的间隙较小。 连续波纹效果: 当一个圆圈的动画结束时,下一个圆圈的动画立即开始,形成连续的波纹效果。 动画循环: 动画无限循环,波纹效果持续不断。