import 'dart:math'; import 'package:flutter/material.dart'; import '../../../constants/app_constants.dart'; /// 流动边框装饰器 class FlowingBorderDecoration extends Decoration { final Animation animation; final Color color; final double width; const FlowingBorderDecoration({ required this.animation, required this.color, this.width = 4.0, }); @override BoxPainter createBoxPainter([VoidCallback? onChanged]) { return _FlowingBorderPainter( animation: animation, color: color, width: width, ); } } class _FlowingBorderPainter extends BoxPainter { final Animation animation; final Color color; final double width; _FlowingBorderPainter({ required this.animation, required this.color, required this.width, }); @override void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { final size = configuration.size!; final rect = offset & size; final radius = Radius.circular(16); final paint = Paint() ..color = color ..strokeWidth = width ..style = PaintingStyle.stroke ..shader = LinearGradient( colors: [color.withAlpha(0), color, color.withAlpha(0)], stops: const [0.0, 0.5, 1.0], transform: GradientRotation(2 * pi * animation.value), ).createShader(rect); canvas.drawRRect(RRect.fromRectAndRadius(rect, radius), paint); } } /// 流动边框容器 class FlowingBorderContainer extends StatefulWidget { final Widget child; final Duration duration; final Color color; final double width; final bool autoStart; const FlowingBorderContainer({ super.key, required this.child, this.duration = const Duration(seconds: 10), this.color = AppConstants.primaryColor, this.width = 4.0, this.autoStart = true, }); @override State createState() => _FlowingBorderContainerState(); } class _FlowingBorderContainerState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController(duration: widget.duration, vsync: this); _animation = Tween( begin: 0, end: 1, ).animate(CurvedAnimation(parent: _controller, curve: Curves.linear)); if (widget.autoStart) { _controller.repeat(); } } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _animation, builder: (context, child) { return Container( padding: EdgeInsets.all(widget.width), decoration: FlowingBorderDecoration( animation: _animation, color: widget.color, width: widget.width, ), child: widget.child, ); }, ); } }