import 'package:flutter/material.dart'; import 'dart:math' as math; /// 环形进度条播放按钮组件 class CircularProgressButton extends StatelessWidget { final bool isPlaying; final double progress; // 0.0 - 1.0 final VoidCallback onPlayPause; final Function(double)? onSeek; // 点击进度条跳转回调 final double size; final Color primaryColor; final Color backgroundColor; final double strokeWidth; const CircularProgressButton({ Key? key, required this.isPlaying, required this.progress, required this.onPlayPause, this.onSeek, this.size = 36.0, required this.primaryColor, this.backgroundColor = Colors.grey, this.strokeWidth = 2.0, }) : super(key: key); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { // 只保留播放/暂停功能,移除进度条点击交互 onPlayPause(); }, child: SizedBox( width: size, height: size, child: Stack( alignment: Alignment.center, children: [ // 背景圆环 CustomPaint( size: Size(size, size), painter: _CircularProgressPainter( progress: 1.0, color: backgroundColor.withValues(alpha: 0.3), strokeWidth: strokeWidth, ), ), // 进度圆环 CustomPaint( size: Size(size, size), painter: _CircularProgressPainter( progress: progress, color: primaryColor, strokeWidth: strokeWidth, ), ), // 播放/暂停按钮 Icon( isPlaying ? Icons.pause : Icons.play_arrow, color: primaryColor, size: size * 0.5, ), ], ), ), ); } } /// 环形进度条绘制器 class _CircularProgressPainter extends CustomPainter { final double progress; final Color color; final double strokeWidth; _CircularProgressPainter({ required this.progress, required this.color, required this.strokeWidth, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = (size.width / 2) - strokeWidth / 2; final paint = Paint() ..color = color ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; // 绘制圆弧,从顶部开始 (-π/2),顺时针绘制 const startAngle = -math.pi / 2; final sweepAngle = 2 * math.pi * progress; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, paint, ); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return oldDelegate is! _CircularProgressPainter || oldDelegate.progress != progress || oldDelegate.color != color || oldDelegate.strokeWidth != strokeWidth; } }