Flutter 自定义进度条组件实现

以下是实现带渐变色与动画效果的进度条组件的完整解决方案:

1. 核心思路
  • 使用CustomPaint绘制自定义进度条
  • 通过LinearGradient实现渐变色效果
  • 结合AnimationController实现平滑动画
  • 支持自定义参数:宽度、高度、渐变色、圆角等
2. 完整代码实现
import 'package:flutter/material.dart';

class GradientProgressBar extends StatefulWidget {
  final double value; // 进度值 (0.0 ~ 1.0)
  final double width;
  final double height;
  final Gradient gradient;
  final Color backgroundColor;
  final double borderRadius;

  const GradientProgressBar({
    Key? key,
    required this.value,
    this.width = 300,
    this.height = 20,
    this.gradient = const LinearGradient(
      colors: [Colors.blue, Colors.green],
    ),
    this.backgroundColor = Colors.grey,
    this.borderRadius = 10,
  }) : super(key: key);

  @override
  _GradientProgressBarState createState() => _GradientProgressBarState();
}

class _GradientProgressBarState extends State<GradientProgressBar>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: widget.value).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
    _controller.forward();
  }

  @override
  void didUpdateWidget(GradientProgressBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.value != widget.value) {
      _animation = Tween<double>(begin: _animation.value, end: widget.value)
          .animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
      _controller.reset();
      _controller.forward();
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Container(
          width: widget.width,
          height: widget.height,
          decoration: BoxDecoration(
            color: widget.backgroundColor,
            borderRadius: BorderRadius.circular(widget.borderRadius),
          ),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(widget.borderRadius),
            child: CustomPaint(
              painter: _ProgressPainter(
                progress: _animation.value,
                gradient: widget.gradient,
              ),
            ),
          ),
        );
      },
    );
  }
}

class _ProgressPainter extends CustomPainter {
  final double progress;
  final Gradient gradient;

  _ProgressPainter({required this.progress, required this.gradient});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..shader = gradient.createShader(Rect.fromLTWH(0, 0, size.width, size.height))
      ..style = PaintingStyle.fill;

    final progressWidth = size.width * progress.clamp(0.0, 1.0);
    canvas.drawRect(Rect.fromLTWH(0, 0, progressWidth, size.height), paint);
  }

  @override
  bool shouldRepaint(covariant _ProgressPainter oldDelegate) {
    return oldDelegate.progress != progress || oldDelegate.gradient != gradient;
  }
}

3. 使用示例
class ExampleScreen extends StatefulWidget {
  @override
  _ExampleScreenState createState() => _ExampleScreenState();
}

class _ExampleScreenState extends State<ExampleScreen> {
  double _progressValue = 0.3;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('渐变进度条')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            GradientProgressBar(
              value: _progressValue,
              width: 300,
              height: 25,
              gradient: LinearGradient(
                colors: [Colors.purple, Colors.orange],
              ),
              backgroundColor: Colors.grey[300]!,
              borderRadius: 12,
            ),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _progressValue = (_progressValue + 0.2).clamp(0.0, 1.0);
                });
              },
              child: Text('增加进度'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 关键特性说明
  1. 渐变色效果

    ..shader = gradient.createShader(Rect.fromLTWH(0, 0, size.width, size.height))
    

    使用着色器实现水平渐变效果,支持任意渐变色组合

  2. 平滑动画

    _animation = Tween<double>(begin: 0, end: widget.value).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
    

    通过CurvedAnimation实现非线性动画效果

  3. 圆角处理

    ClipRRect(
      borderRadius: BorderRadius.circular(widget.borderRadius),
    )
    

    使用ClipRRect裁剪超出圆角范围的内容

  4. 动态更新

    void didUpdateWidget() {
      // 进度值变化时重置动画
    }
    

    当进度值变化时自动重新启动动画

5. 自定义参数
参数名 类型 默认值 说明
value double 必填 当前进度值 (0.0~1.0)
width double 300 进度条宽度
height double 20 进度条高度
gradient Gradient 蓝绿渐变 渐变色配置
backgroundColor Color 灰色 背景色
borderRadius double 10 圆角半径

此组件完全遵循 Material Design 规范,可直接集成到现有 Flutter 项目中,支持动态更新进度值并带有平滑过渡动画。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐