This widget manages animations for child widgets, providing smooth transitions when children are added, removed, or reordered.
Properties
The list of child widgets to display in the stack.
Function that builds animated widgets from children and animations.
The duration of animations.
Position in the animation timeline where cross-fade occurs (0.0 to 1.0).
Whether to animate the initial child.
alignment
AlignmentGeometry
default:"AlignmentDirectional.topStart"
How to align the children.
The text direction for the stack.
fit
StackFit
default:"StackFit.loose"
How to size the non-positioned children.
clipBehavior
Clip
default:"Clip.hardEdge"
The clip behavior for the stack.
Constructor
const AnimatedStack({
Key? key,
required Duration duration,
required AnimationBuilder animation,
required List<Widget> children,
bool initialAnimation = true,
double crossFadePosition = 0.5,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection? textDirection,
StackFit fit = StackFit.loose,
Clip clipBehavior = Clip.hardEdge
})
Animation builder function.
Whether to animate the initial child.
Position for cross-fade transition.
alignment
AlignmentGeometry
default:"AlignmentDirectional.topStart"
Alignment for children.
fit
StackFit
default:"StackFit.loose"
How to size non-positioned children.
clipBehavior
Clip
default:"Clip.hardEdge"
Clip behavior.
Type definitions
AnimationBuilder
typedef AnimationBuilder = Widget Function(
Widget child,
Animation<double> animation
)
Function type for building animated widgets. Takes a child widget and an animation, returns an animated widget.
Example
import 'package:flutter/material.dart';
import 'package:navigation_utils/navigation_utils.dart';
class AnimatedStackExample extends StatefulWidget {
@override
State<AnimatedStackExample> createState() => _AnimatedStackExampleState();
}
class _AnimatedStackExampleState extends State<AnimatedStackExample> {
List<Widget> pages = [];
@override
void initState() {
super.initState();
pages = [
Container(key: ValueKey('page1'), color: Colors.red),
];
}
void addPage() {
setState(() {
pages.add(
Container(
key: ValueKey('page${pages.length + 1}'),
color: Colors.blue,
),
);
});
}
void removePage() {
if (pages.length > 1) {
setState(() {
pages.removeLast();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: AnimatedStack(
duration: Duration(milliseconds: 300),
children: pages,
animation: (child, animation) {
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
},
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: addPage,
child: Icon(Icons.add),
),
SizedBox(height: 16),
FloatingActionButton(
onPressed: removePage,
child: Icon(Icons.remove),
),
],
),
);
}
}
Notes
- All child widgets must have unique keys for proper animation tracking
- The widget maintains animation controllers internally and disposes them automatically
- Cross-fade position determines when the incoming animation starts relative to the outgoing animation
- The widget optimizes rendering by using Offstage for non-visible children