You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

114 lines
3.0 KiB

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;
}
}