| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- class ProgressBar extends StatefulWidget {
- final String title;
- final int? value;
- final Color color;
- const ProgressBar({
- super.key,
- required this.title,
- required this.value,
- required this.color,
- });
- @override
- State<ProgressBar> createState() => _ProgressBarState();
- }
- class _ProgressBarState extends State<ProgressBar>
- with SingleTickerProviderStateMixin {
- late AnimationController _animationController;
- late Animation<double> _progressAnimation;
- late Tween<double> _valueTween;
- @override
- void initState() {
- super.initState();
- _animationController = AnimationController(
- vsync: this,
- duration: const Duration(seconds: 2),
- );
- _setupAnimation();
- _startAnimation();
- }
- @override
- void didUpdateWidget(covariant ProgressBar oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (oldWidget.value != widget.value) {
- _setupAnimation();
- _startAnimation();
- }
- }
- /// 设置动画曲线和范围
- void _setupAnimation() {
- if (widget.value == null) {
- _valueTween = Tween<double>(begin: 0.0, end: 1.0);
- } else {
- _valueTween = Tween<double>(
- begin: 0,
- end: _getTargetProgress(),
- );
- }
- _progressAnimation = _valueTween.animate(
- CurvedAnimation(parent: _animationController, curve: Curves.easeOut),
- );
- }
- double _getTargetProgress() {
- return (widget.value ?? 0) / 100.0;
- }
- void _startAnimation() {
- _animationController.stop();
- if (widget.value == null) {
- _animationController.repeat();
- } else {
- _animationController
- ..reset()
- ..forward();
- }
- }
- @override
- void dispose() {
- _animationController.dispose();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- final bool isLoading = widget.value == null;
- return Row(
- children: [
- Text(widget.title),
- SizedBox(width: 3.w),
- Expanded(
- child: Stack(
- children: [
- // 背景条
- Container(
- height: 11.h,
- decoration: BoxDecoration(
- color: widget.color.withOpacity(0.3),
- borderRadius: BorderRadius.circular(53.r),
- ),
- ),
- // 动画进度条
- AnimatedBuilder(
- animation: _progressAnimation,
- builder: (_, __) {
- final double progress = _progressAnimation.value;
- return FractionallySizedBox(
- widthFactor: progress.clamp(0.0, 1.0),
- child: Container(
- height: 11.h,
- decoration: BoxDecoration(
- color: widget.color,
- borderRadius: BorderRadius.circular(53.r),
- ),
- ),
- );
- },
- ),
- // 中间文字
- Positioned.fill(
- child: Center(
- child: Text(
- isLoading
- ? "加载中..."
- : "${(widget.value ?? 0).clamp(0, 100)}%",
- style: TextStyle(
- color: Colors.white,
- fontSize: 7.sp,
- fontWeight: FontWeight.w500,
- shadows: [
- Shadow(
- color: Colors.black.withOpacity(0.6),
- offset: Offset(1, 1),
- blurRadius: 3.r,
- ),
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ],
- );
- }
- }
|