diff --git a/lib/moon_design.dart b/lib/moon_design.dart index 0e02ce61..91eba8fd 100644 --- a/lib/moon_design.dart +++ b/lib/moon_design.dart @@ -18,6 +18,7 @@ export 'package:moon_design/src/theme/sizes.dart'; export 'package:moon_design/src/theme/theme.dart'; export 'package:moon_design/src/theme/typography/text_styles.dart'; export 'package:moon_design/src/theme/typography/typography.dart'; +export 'package:moon_design/src/utils/animated_icon_theme.dart'; export 'package:moon_design/src/utils/extensions.dart'; export 'package:moon_design/src/utils/measure_size.dart'; export 'package:moon_design/src/utils/moon_icon.dart'; diff --git a/lib/src/utils/animated_icon_theme.dart b/lib/src/utils/animated_icon_theme.dart new file mode 100644 index 00000000..831850aa --- /dev/null +++ b/lib/src/utils/animated_icon_theme.dart @@ -0,0 +1,91 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class AnimatedIconTheme extends StatefulWidget { + final Color color; + final double? size; + final Curve curve; + final Duration duration; + final Widget child; + + const AnimatedIconTheme({ + super.key, + required this.color, + this.size, + required this.curve, + required this.duration, + required this.child, + }); + + @override + State createState() => _AnimatedIconThemeState(); +} + +class _AnimatedIconThemeState extends State with SingleTickerProviderStateMixin { + Color _initialColor = Colors.transparent; + Color _targetColor = Colors.transparent; + + AnimationController get controller => _controller; + late final AnimationController _controller = AnimationController( + duration: widget.duration, + debugLabel: kDebugMode ? widget.toStringShort() : null, + vsync: this, + ); + + Animation get animation => _animation; + late CurvedAnimation _animation = _createCurve(); + + CurvedAnimation _createCurve() { + return CurvedAnimation(parent: _controller, curve: widget.curve); + } + + @override + void initState() { + super.initState(); + _initialColor = widget.color; + } + + @override + void didUpdateWidget(AnimatedIconTheme oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.curve != oldWidget.curve) { + _animation.dispose(); + _animation = _createCurve(); + } + + _controller.duration = widget.duration; + + if (widget.color != oldWidget.color) { + _targetColor = widget.color; + _initialColor = oldWidget.color; + _controller + ..value = 0.0 + ..forward(); + } + } + + @override + void dispose() { + _animation.dispose(); + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return RepaintBoundary( + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) => IconTheme( + data: IconThemeData.lerp( + IconThemeData(color: _initialColor, size: widget.size), + IconThemeData(color: _targetColor, size: widget.size), + _animation.value, + ), + child: child!, + ), + child: widget.child, + ), + ); + } +} diff --git a/lib/src/widgets/chips/chip.dart b/lib/src/widgets/chips/chip.dart index c1a7dfaa..06879710 100644 --- a/lib/src/widgets/chips/chip.dart +++ b/lib/src/widgets/chips/chip.dart @@ -6,7 +6,7 @@ import 'package:moon_design/src/theme/chip/chip_sizes.dart'; import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/effects/hover_effects.dart'; import 'package:moon_design/src/theme/theme.dart'; -import 'package:moon_design/src/utils/extensions.dart'; +import 'package:moon_design/src/utils/animated_icon_theme.dart'; import 'package:moon_design/src/widgets/base_control.dart'; enum MoonChipSize { @@ -164,7 +164,6 @@ class MoonChip extends StatelessWidget { } Color _getTextColor({ - required bool isDarkMode, required Color backgroundColor, required Color activeColor, required Color? textColor, @@ -246,7 +245,6 @@ class MoonChip extends StatelessWidget { final Color effectiveTextColor = _getTextColor( isActive: canAnimate, - isDarkMode: context.isDarkMode, activeColor: effectiveActiveColor, backgroundColor: effectiveBackgroundColor, textColor: textColor, @@ -287,8 +285,11 @@ class MoonChip extends StatelessWidget { ), ), ), - child: IconTheme( - data: IconThemeData(color: effectiveTextColor, size: effectiveMoonChipSize.iconSizeValue), + child: AnimatedIconTheme( + duration: effectiveHoverEffectDuration, + curve: effectiveHoverEffectCurve, + color: effectiveTextColor, + size: effectiveMoonChipSize.iconSizeValue, child: AnimatedDefaultTextStyle( duration: effectiveHoverEffectDuration, curve: effectiveHoverEffectCurve,