This is what I would like to achieve:
- When the widget appears I want the animation to be delayed by 500 ms and fade in for 300 ms
- When the widget disappears I want the animation to start immediately and fade out for 300 ms
Currently when using AnimatedOpacity I achieve it by simply calling setState after a dedicated Timer(Duration(milliseconds: 500)), but I would love to define this declaratively.
Is there a way to achieve it?
I achieved this effect using AnimatedOpacity as follows:
import 'dart:async';
import 'package:flutter/widgets.dart';
/// Widget that delays opacity change when widget
/// appears (in) or disappears (out)
class DelayedAnimatedOpacity extends StatefulWidget {
const DelayedAnimatedOpacity({
super.key,
Duration? delayIn,
Duration? delayOut,
this.duration = const Duration(milliseconds: 500),
required this.child,
required this.visible,
}) : delayIn = delayIn ?? const Duration(milliseconds: 500),
delayOut = delayOut ?? Duration.zero;
final Duration delayIn;
final Duration delayOut;
final Duration duration;
final Widget child;
final bool visible;
@override
State<DelayedAnimatedOpacity> createState() => _DelayedAnimatedOpacityState();
}
class _DelayedAnimatedOpacityState extends State<DelayedAnimatedOpacity> {
bool visible = false;
Timer? _timer;
@override
void initState() {
super.initState();
if (widget.visible) {
_timer = Timer(widget.delayIn, () {
if (mounted) {
setState(() {
visible = true;
});
}
});
}
}
@override
void didUpdateWidget(covariant DelayedAnimatedOpacity oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.visible != visible) {
if (widget.visible) {
_timer?.cancel();
_timer = Timer(widget.delayIn, () {
if (mounted) {
setState(() {
visible = true;
});
}
});
} else {
_timer?.cancel();
_timer = Timer(widget.delayOut, () {
if (mounted) {
setState(() {
visible = false;
});
}
});
}
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedOpacity(
duration: widget.duration,
opacity: visible ? 1 : 0,
child: widget.child,
);
}
}
This is what I would like to achieve:
Currently when using
AnimatedOpacityI achieve it by simply calling setState after a dedicatedTimer(Duration(milliseconds: 500)), but I would love to define this declaratively.Is there a way to achieve it?
I achieved this effect using AnimatedOpacity as follows: