library glowy_borderspertino.dart; import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; class AnimatedGradientBorder extends StatefulWidget { const AnimatedGradientBorder( {Key? key, required this.child, required this.gradientColors, required this.borderRadius, this.animationTime, this.borderSize, this.animationProgress, this.stretchAlongAxis = false, this.stretchAxis = Axis.horizontal}); final Widget child; final double? borderSize; final List gradientColors; final BorderRadiusGeometry borderRadius; final int? animationTime; final double? animationProgress; final bool stretchAlongAxis; final Axis stretchAxis; @override State createState() => AnimatedGradientState(); } class AnimatedGradientState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _angleAnimation; @override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: Duration(seconds: widget.animationTime ?? 2)); _controller.addListener(() => setState(() {})); _angleAnimation = Tween(begin: 0.1, end: 2 * math.pi).animate(_controller); if (widget.animationProgress != null) { _controller.forward(); } else { _controller.repeat(); } } @override void dispose() { _controller.dispose(); super.dispose(); } @override void didUpdateWidget(covariant AnimatedGradientBorder oldWidget) { super.didUpdateWidget(oldWidget); double? animateTo = widget.animationProgress; if (animateTo != null) { _controller.animateTo(animateTo); } else { _controller.repeat(); } } @override Widget build(BuildContext context) { double? negativeMargin = -1.0 * (widget.borderSize ?? 0); return Container( padding: EdgeInsets.all(widget.borderSize ?? 0), clipBehavior: Clip.hardEdge, decoration: BoxDecoration( color: MyColors.kWhiteColor, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3), ), ], ), child: Stack(alignment: Alignment.center, clipBehavior: Clip.none, children: [ Positioned( top: negativeMargin, left: negativeMargin, right: negativeMargin, bottom: negativeMargin, child: AnimatedGradientContainer( gradientColors: widget.gradientColors, borderRadius: widget.borderRadius, gradientAngle: _angleAnimation.value, )), widget.child, // BackdropFilter( // filter: ImageFilter.blur(sigmaX: widget.glowSize ?? 0, sigmaY: widget.glowSize ?? 0), // child: Stack( // alignment: Alignment.center, // clipBehavior: Clip.none, // children: [ // Positioned( // top: negativeMargin, // right: negativeMargin, // left: negativeMargin, // bottom: negativeMargin, // child: AnimatedGradientContainer( // gradientColors: widget.gradientColors, // borderRadius: widget.borderRadius, // gradientAngle: _angleAnimation.value, // )), // if (widget.stretchAlongAxis) // SizedBox( // width: widget.stretchAxis == Axis.horizontal ? double.infinity : null, // height: widget.stretchAxis == Axis.vertical ? double.infinity : null, // child: widget.child, // ) // else // widget.child, // ], // ), // ), ]), ); } } class AnimatedGradientContainer extends StatelessWidget { const AnimatedGradientContainer({Key? key, required this.gradientColors, required this.gradientAngle, required this.borderRadius}); final List gradientColors; final double gradientAngle; final BorderRadiusGeometry borderRadius; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( borderRadius: borderRadius, gradient: SweepGradient( colors: [...gradientColors, ...gradientColors.reversed], stops: _generateColorStops([...gradientColors, ...gradientColors.reversed]), transform: GradientRotation(gradientAngle)))); } List _generateColorStops(List colors) { return colors.asMap().entries.map((entry) { double percentageStop = entry.key / colors.length; return percentageStop; }).toList(); } }