You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现带渐变圆角的自定义Spinner及ease-in动画

Flutter 自定义渐变圆角Spinner 实现

完整实现代码

import 'package:flutter/material.dart';

class GradientRoundSpinner extends StatefulWidget {
  final double size;
  final double strokeWidth;

  const GradientRoundSpinner({
    super.key,
    this.size = 60.0,
    this.strokeWidth = 6.0,
  });

  @override
  State<GradientRoundSpinner> createState() => _GradientRoundSpinnerState();
}

class _GradientRoundSpinnerState extends State<GradientRoundSpinner> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _rotationAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1500),
    )..repeat();

    _rotationAnimation = Tween<double>(begin: 0, end: 2 * 3.1415926)
        .animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn));
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _rotationAnimation,
      builder: (context, child) {
        return Transform.rotate(
          angle: _rotationAnimation.value,
          child: CustomPaint(
            size: Size(widget.size, widget.size),
            painter: _GradientSpinnerPainter(
              strokeWidth: widget.strokeWidth,
              gradient: const SweepGradient(
                colors: [
                  Color(0xFFFF9702),
                  Color(0xFFFE6F27),
                  Color(0xFFFE395D),
                  Color(0xFFFE0096),
                ],
                startAngle: 0,
                endAngle: 2 * 3.1415926,
              ),
            ),
          ),
        );
      },
    );
  }
}

class _GradientSpinnerPainter extends CustomPainter {
  final double strokeWidth;
  final Gradient gradient;

  _GradientSpinnerPainter({
    required this.strokeWidth,
    required this.gradient,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = (size.width - strokeWidth) / 2;

    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round
      ..shader = gradient.createShader(Rect.fromCircle(center: center, radius: radius));

    // 绘制3/4圆弧形成缺口,增强动态感
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      0,
      2 * 3.1415926 * 0.75,
      false,
      paint,
    );
  }

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

// 使用示例
void main() {
  runApp(const MaterialApp(
    home: Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: GradientRoundSpinner(size: 80, strokeWidth: 8),
      ),
    ),
  ));
}

关键细节说明

  • 渐变配置:用SweepGradient实现环形渐变,完全匹配你提供的4种十六进制颜色值,覆盖整个圆周。
  • 圆角效果:通过strokeCap = StrokeCap.round设置圆弧两端为圆角,贴合参考图样式。
  • Ease-in动画:将动画曲线设为Curves.easeIn,配合AnimationController.repeat()实现循环缓入旋转效果。
  • 自定义参数:支持通过size和strokeWidth调整Spinner的尺寸和线条粗细,适配不同布局场景。
  • 缺口设计:绘制3/4长度的圆弧形成缺口,强化加载动画的动态感;若需要完整圆环,可将drawArc的角度参数改为2*3.1415926。

内容的提问来源于stack exchange,提问作者Tharuneshwar S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:37:40