From db07ab78bf60193b48cf542af4b4fe53f064980f Mon Sep 17 00:00:00 2001 From: mikes222 Date: Fri, 2 Feb 2024 21:48:03 +0100 Subject: [PATCH] Introduction of SwitchEffect() --- README.md | 2 + lib/flutter_animate.dart | 5 ++- lib/src/switch_effect.dart | 89 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 lib/src/switch_effect.dart diff --git a/README.md b/README.md index a57c3ca..b466e90 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,8 @@ text.animate().fadeOut(300.ms) // fade out & then... .swap(builder: (_, child) => child.animate().fadeIn()) ``` +See also SwitchEffect() for an alternative implementation of animations which switches between two or more childs. + ShaderEffect ---------------------------------------- `ShaderEffect` makes it easy to apply animated GLSL fragment shaders to widgets. diff --git a/lib/flutter_animate.dart b/lib/flutter_animate.dart index 39cc6fd..2224245 100644 --- a/lib/flutter_animate.dart +++ b/lib/flutter_animate.dart @@ -1,7 +1,8 @@ +export 'src/adapters/adapters.dart'; export 'src/animate.dart'; export 'src/animate_list.dart'; export 'src/effect_list.dart'; -export 'src/flutter_animate.dart'; -export 'src/adapters/adapters.dart'; export 'src/effects/effects.dart'; export 'src/extensions/extensions.dart'; +export 'src/flutter_animate.dart'; +export 'src/switch_effect.dart'; diff --git a/lib/src/switch_effect.dart b/lib/src/switch_effect.dart new file mode 100644 index 0000000..fbeee11 --- /dev/null +++ b/lib/src/switch_effect.dart @@ -0,0 +1,89 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_animate/flutter_animate.dart'; + +/// A widget for implementing switch effects. When calling the first time the given [child] will be animated with [inEffects]. +/// When the widget is called again with a different child the [outEffects] of the previous widget instance will be applied to +/// the [child] handled by the previous widget immediately following with the animation of the new child by using the +/// [inEffects] of the new widget. Before switching the childs the optional callback method is triggered. +class SwitchEffect extends StatefulWidget { + /// the child for this animation + final Widget child; + + /// a list of effects to apply to the child when the child will be shown. Default is fadeIn() + final List? inEffects; + + /// a list of effects to apply to the child when the child should be replaced by another child. Default is fadeOut() + final List? outEffects; + + /// Callback function which will be triggered right after the outEffects are completed and before the new child will be swapped in for the inEffects + final void Function(BuildContext)? onSwap; + + /// Callbak function which will be triggered after all effects are completed + final void Function(BuildContext)? onComplete; + + const SwitchEffect( + {super.key, + required this.child, + this.inEffects, + this.outEffects, + this.onSwap, + this.onComplete}); + + @override + State createState() { + return _SwitchEffectState(); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +class _SwitchEffectState extends State { + @override + SwitchEffect get widget => super.widget as SwitchEffect; + + /// when changing the child of the widget this field will be filled with the child of the previous widget. + Widget? _lastChild; + + List? _lastOutEffects; + + @override + Widget build(BuildContext context) { + if (_lastChild != null) { + return Animate( + key: GlobalKey(), + effects: _lastOutEffects ?? EffectList().fadeOut(), + onComplete: (_) { + if (widget.onSwap != null) widget.onSwap!(context); + }, + child: _lastChild!, + ).then().swap( + duration: 0.seconds, + delay: 0.seconds, + builder: (BuildContext context, _) => Animate( + effects: widget.inEffects ?? EffectList().fadeIn(), + onComplete: (_) { + if (widget.onComplete != null) widget.onComplete!(context); + }, + child: widget.child, + )); + } + + return Animate( + key: GlobalKey(), + effects: widget.inEffects ?? EffectList().fadeIn(), + onComplete: (_) { + if (widget.onComplete != null) widget.onComplete!(context); + }, + child: widget.child, + ); + } + + @override + void didUpdateWidget(covariant SwitchEffect oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.child != widget.child) { + _lastChild = oldWidget.child; + _lastOutEffects = oldWidget.outEffects; + } + } +}