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

Flutter中如何给Container实现无限循环的动画边框效果?

实现方案

你需要配合AnimationController做无限动画,结合PathMetric动态截取正方形边框的路径片段,就能实现循环滚动的动画边框效果,完整实现代码如下:

1. 主页面Widget代码(包含动画控制器)

import 'package:flutter/material.dart';

class AnimatedBorderContainer extends StatefulWidget {
  final double size;
  final Color borderColor;
  final double strokeWidth;
  final Duration duration;

  const AnimatedBorderContainer({
    super.key,
    this.size = 200,
    this.borderColor = Colors.blue,
    this.strokeWidth = 3,
    this.duration = const Duration(seconds: 2),
  });

  @override
  State<AnimatedBorderContainer> createState() => _AnimatedBorderContainerState();
}

class _AnimatedBorderContainerState extends State<AnimatedBorderContainer> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: widget.duration);
    _animation = Tween<double>(begin: 0, end: 1).animate(_controller);
    // 设置无限循环播放
    _controller.repeat();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return CustomPaint(
          size: Size(widget.size, widget.size),
          painter: RadialPainter(
            progress: _animation.value,
            color: widget.borderColor,
            strokeWidth: widget.strokeWidth,
            strokeCap: StrokeCap.round,
            paintingStyle: PaintingStyle.stroke,
            // 这里设置边框显示的片段长度,0.2代表总周长的20%
            segmentLength: 0.2,
          ),
        );
      },
    );
  }
}

2. 修改后的RadialPainter代码

class RadialPainter extends CustomPainter {
  final Color color;
  final StrokeCap strokeCap;
  final PaintingStyle paintingStyle;
  final double strokeWidth;
  final double progress;
  final double segmentLength;

  RadialPainter({
    required this.color,
    required this.strokeWidth,
    required this.strokeCap,
    required this.paintingStyle,
    required this.progress,
    required this.segmentLength,
  });

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..strokeWidth = strokeWidth
      ..color = color
      ..style = paintingStyle
      ..strokeCap = strokeCap;

    // 构建完整的正方形路径
    Path path = Path()
      ..moveTo(0, 0)
      ..lineTo(size.width, 0)
      ..lineTo(size.width, size.height)
      ..lineTo(0, size.height)
      ..close();

    // 计算路径总长度
    PathMetric pathMetric = path.computeMetrics().first;
    double totalLength = pathMetric.length;

    // 计算当前片段的起止点
    double start = progress * totalLength;
    double end = start + segmentLength * totalLength;

    Path segmentPath;
    if (end <= totalLength) {
      segmentPath = pathMetric.extractPath(start, end);
    } else {
      // 片段跨路径首尾时,拼接两部分路径
      segmentPath = pathMetric.extractPath(start, totalLength);
      segmentPath.addPath(pathMetric.extractPath(0, end % totalLength), Offset.zero);
    }

    canvas.drawPath(segmentPath, paint);
  }

  @override
  bool shouldRepaint(RadialPainter oldDelegate) {
    return oldDelegate.progress != progress;
  }
}

使用方法

直接在需要的地方引入AnimatedBorderContainer即可,可自定义尺寸、边框颜色、动画速度、线条粗细等参数:

AnimatedBorderContainer(
  size: 300,
  borderColor: Colors.green,
  strokeWidth: 4,
  duration: Duration(seconds: 3),
)

如果需要给边框内部加内容,直接在CustomPaint的child参数里传入你的Container即可。


内容的提问来源于stack exchange,提问作者Mariam Younes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 11:48:04