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