┌─────────────────────────────┐ │ Simple Animation Screen │ │ │ │ ■■■■■■■■ │ │ ■ ■ │ │ ■ ■ │ │ ■■■■■■■■ │ │ │ │ [Start Animation] [Stop] │ └─────────────────────────────┘
AnimationController in Flutter - Mini App: Build & Ship
import 'package:flutter/material.dart'; class SimpleAnimationScreen extends StatefulWidget { @override State<SimpleAnimationScreen> createState() => _SimpleAnimationScreenState(); } class _SimpleAnimationScreenState extends State<SimpleAnimationScreen> with SingleTickerProviderStateMixin { late AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 2), ); // TODO: Add animation behavior here } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Simple Animation Screen')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // TODO: Add animated square here const SizedBox(height: 40), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { // TODO: Start animation }, child: const Text('Start Animation'), ), const SizedBox(width: 20), ElevatedButton( onPressed: () { // TODO: Stop animation }, child: const Text('Stop'), ), ], ), ], ), ), ); } }
import 'package:flutter/material.dart'; class SimpleAnimationScreen extends StatefulWidget { @override State<SimpleAnimationScreen> createState() => _SimpleAnimationScreenState(); } class _SimpleAnimationScreenState extends State<SimpleAnimationScreen> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _sizeAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 2), ); _sizeAnimation = Tween<double>(begin: 100, end: 200).animate(_controller); _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _controller.reverse(); } else if (status == AnimationStatus.dismissed) { _controller.forward(); } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Simple Animation Screen')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedBuilder( animation: _sizeAnimation, builder: (context, child) { return Container( width: _sizeAnimation.value, height: _sizeAnimation.value, color: Colors.blue, ); }, ), const SizedBox(height: 40), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { _controller.forward(); }, child: const Text('Start Animation'), ), const SizedBox(width: 20), ElevatedButton( onPressed: () { _controller.stop(); }, child: const Text('Stop'), ), ], ), ], ), ), ); } }
We use AnimationController to control the animation timing. The controller runs for 2 seconds. We create a Tween that changes the size from 100 to 200 pixels. The AnimatedBuilder rebuilds the square container whenever the animation value changes, updating its width and height.
We listen to the animation status to make it reverse direction when it finishes growing, and forward again when it finishes shrinking. This creates a smooth back-and-forth effect.
The 'Start Animation' button calls _controller.forward() to begin the animation. The 'Stop' button calls _controller.stop() to pause it.
This example shows how to use AnimationController simply and clearly to animate a widget's size.
┌─────────────────────────────┐ │ Simple Animation Screen │ │ │ │ ■■■■■■■■■■■■■■ │ │ ■ ■ │ │ ■ ■ │ │ ■■■■■■■■■■■■■■ │ │ │ │ [Start Animation] [Stop] │ └─────────────────────────────┘
Practice
AnimationController in Flutter animations?Solution
Step 1: Understand AnimationController purpose
The AnimationController is designed to manage animation timing and progress in Flutter.Step 2: Compare with other options
Displaying images, handling user input events, and managing network requests relate to other Flutter features, not animation control.Final Answer:
To control the timing and progress of an animation -> Option CQuick Check:
AnimationController controls animation timing = A [OK]
- Confusing AnimationController with UI widgets
- Thinking it handles user input
- Assuming it manages network or data
AnimationController inside a StatefulWidget with a 2-second duration?Solution
Step 1: Check correct parameter types
Thedurationparameter requires aDurationobject, andvsyncmust be provided.Step 2: Validate each option
AnimationController(vsync: this, duration: Duration(seconds: 2)) correctly usesDuration(seconds: 2)andvsync: this. Constructors passing an integer for duration misuse the type. The constructor with only duration missesvsync.Final Answer:
AnimationController(vsync: this, duration: Duration(seconds: 2)) -> Option DQuick Check:
Duration needs Duration object and vsync required = A [OK]
- Passing integer instead of Duration
- Omitting vsync parameter
- Swapping parameter order incorrectly
StatefulWidget:
late AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
What happens when this widget is removed from the screen?Solution
Step 1: Analyze dispose method
Thedispose()method callscontroller.dispose(), which frees animation resources.Step 2: Understand animation lifecycle
Callingdispose()stops the animation and prevents memory leaks when the widget is removed.Final Answer:
The animation stops and resources are freed properly -> Option AQuick Check:
Dispose frees resources and stops animation = B [OK]
- Forgetting to call dispose causing leaks
- Assuming animation runs after widget removal
- Expecting animation to restart automatically
class MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {
late AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(duration: Duration(seconds: 3));
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}Solution
Step 1: Check AnimationController constructor
The constructor requires avsyncparameter to optimize animation performance.Step 2: Identify missing parameter
The code omitsvsync: this, causing an error.Final Answer:
Missing vsync parameter in AnimationController constructor -> Option BQuick Check:
vsync missing in AnimationController = D [OK]
- Omitting vsync parameter
- Passing wrong type for duration
- Forgetting to mix in SingleTickerProviderStateMixin
AnimationController. Which code snippet correctly sets up the controller to repeat the animation forever and reverse direction each time?Solution
Step 1: Understand repeat method parameters
Therepeat()method can takereverse: trueto make animation go back and forth.Step 2: Evaluate each option
controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat(reverse: true); usesrepeat(reverse: true)correctly. controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..forward(); only plays forward once. controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat(); repeats but does not reverse. controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..reverse(); calls reverse once, not repeating.Final Answer:
controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat(reverse: true); -> Option AQuick Check:
repeat with reverse true = C [OK]
- Using forward() instead of repeat()
- Forgetting reverse: true for back-and-forth
- Calling reverse() once instead of repeating
Ready to prove it?
Pass the test and this pattern moves unknown
