Getting Started with Flutter: Install, Your First App and Project Structure
A step-by-step guide from installing the Flutter SDK to running your first app and understanding the project structure, with tips that save you time at the start.
Good animation brings an app to life, but it has to be built the right way. This article covers implicit and explicit animations, Hero transitions and the performance tips that matter, with code.

Good animations make an app feel alive, but badly implemented ones slow it down. Flutter has two families of animation, and choosing the right one is half the work.
Just provide the new value; Flutter animates the path from the old value to the new. Widgets such as AnimatedContainer, AnimatedOpacity, AnimatedAlign and AnimatedSwitcher:
AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
width: expanded ? 240 : 120,
height: 120,
decoration: BoxDecoration(
color: expanded ? Colors.indigo : Colors.teal,
borderRadius: BorderRadius.circular(expanded ? 32 : 12),
),
)Every setState that changes expanded produces a smooth transition. In about 80% of cases this is all you need.
When no ready-made implicit widget fits:
TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: progress),
duration: const Duration(milliseconds: 600),
builder: (context, value, _) => LinearProgressIndicator(value: value),
)When you want full control (start, stop, repeat, reverse):
class _PulseState extends State<Pulse> with SingleTickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
)..repeat(reverse: true);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ScaleTransition(
scale: Tween(begin: 0.9, end: 1.1).animate(_controller),
child: const FlutterLogo(size: 80),
);
}
}The golden rule: always dispose the controller.
If two widgets on two screens share the same tag, Flutter turns one into the other (a flight) during navigation:
Hero(tag: 'product-$id', child: Image.network(url))AnimatedBuilder with its child parameter so the static part of the tree is not rebuilt every frame.RepaintBoundary.Opacity on a large subtree; FadeTransition or AnimatedOpacity is cheaper.transform or opacity are the cheapest; avoid changing size and layout every frame.Curves.easeOut, easeInOut), not linear.If a user enabled "reduce motion" in their device settings, respect it with MediaQuery.disableAnimationsOf(context).
The FastFlutter VIP course takes you from zero to a published app, with direct support from the instructor.