Master Flutter's animation system with implicit and explicit animations, hero transitions, physics-based motion, and custom transitions. Use when adding animations, creating transitions, implementing hero effects, or building interactive animated experiences.
From flutter-corenpx claudepluginhub aaronbassett/agent-foundry --plugin flutter-coreThis skill uses the workspace's default tool permissions.
examples/interactive-animations.mdexamples/staggered-animations.mdreferences/custom-transitions.mdreferences/explicit-animations.mdreferences/hero-transitions.mdreferences/implicit-animations.mdreferences/physics-simulations.mdSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides implementation of event-driven hooks in Claude Code plugins using prompt-based validation and bash commands for PreToolUse, Stop, and session events.
Master Flutter's animation system to create smooth, performant, and delightful user experiences through implicit animations, explicit control, hero transitions, and physics-based motion.
Flutter's animation framework is built on a fundamental principle: well-designed animations make UIs feel more intuitive, contribute to a polished experience, and provide visual feedback that guides users through your application. The framework offers a comprehensive toolkit ranging from simple, pre-packaged implicit animations to fully customizable explicit animations with physics simulations.
Understanding when and how to use each type of animation is crucial for building modern Flutter applications. This skill provides comprehensive guidance on Flutter's animation capabilities, performance optimization techniques, and best practices for creating smooth, responsive animations.
Flutter approaches animations through a layered architecture that balances ease of use with powerful control:
Progressive Complexity: Start with the simplest solution that meets your needs. Flutter encourages using implicit animations for straightforward transitions, explicit animations when you need coordination, and custom implementations only when necessary. This progressive approach ensures you're not adding unnecessary complexity to your codebase.
Declarative Animation: Unlike imperative animation systems where you manually calculate and set values frame-by-frame, Flutter's declarative approach lets you specify what should change and the framework handles the interpolation. You describe the start and end states, and Flutter smoothly transitions between them.
Composition Over Inheritance: Flutter's animation classes are designed to compose together. A CurvedAnimation wraps an AnimationController, a Tween transforms values, and these pieces combine to create sophisticated effects without deep inheritance hierarchies.
Performance First: The animation system is optimized for 60fps (or 120fps on capable devices) by default. The framework provides tools like RepaintBoundary and AnimatedBuilder to minimize unnecessary rebuilds and ensure smooth performance even on lower-end devices.
The choice between implicit and explicit animations is one of the first decisions you'll make when adding motion to your Flutter app.
Implicit animations are Flutter widgets that automatically animate property changes over a specified duration. They derive from ImplicitlyAnimatedWidget and handle all animation controller management internally.
When to Use Implicit Animations:
Common Implicit Animated Widgets:
AnimatedContainer - Animates container properties like size, color, padding, and bordersAnimatedOpacity - Fades widgets in and outAnimatedPositioned - Animates position changes within a StackAnimatedAlign - Animates alignment changesAnimatedPadding - Animates padding transitionsAnimatedSwitcher - Cross-fades between different widgetsTweenAnimationBuilder - Creates custom implicit animations for any propertyKey Advantages:
Example Use Case: A button that changes color when pressed, a container that expands when selected, or a widget that fades in when data loads.
Explicit animations give you full control over the animation lifecycle through AnimationController. You manage when animations start, stop, reverse, and repeat.
When to Use Explicit Animations:
Core Components:
AnimationController - The animation timeline controllerTween - Maps animation values to custom rangesCurvedAnimation - Applies easing curvesAnimatedBuilder - Efficiently rebuilds only animated partsAnimatedWidget - Base class for reusable animated widgetsKey Advantages:
Example Use Case: A loading spinner that continuously rotates, a card that flips over with coordinated opacity and rotation changes, or an interactive animation that follows user drag gestures.
Hero animations, also known as shared element transitions, create visual continuity between screens by animating a widget from one route to another. This pattern is ubiquitous in modern mobile apps - think of tapping a photo thumbnail that smoothly expands into a full-screen view.
How Hero Animations Work:
Hero widgets sharing the same tagBehind the Scenes:
Flutter doesn't actually move the widget between screens. Instead, it:
RectTweenMaterialRectArcTween for curved motion pathsStandard Hero Pattern: The most common pattern involves an image or card that appears on a list screen and expands to fill the detail screen. The hero tag uniquely identifies which elements should animate together.
Radial Hero Animations:
A variant where the hero transforms from circular to rectangular (or vice versa) while flying between screens. This requires using MaterialRectCenterArcTween and RadialExpansion to maintain the circular clipping during the animation.
Best Practices:
Material(color: Colors.transparent) for smooth transitionstimeDilation to slow animations during development and debuggingCreating smooth animations requires understanding Flutter's rendering pipeline and avoiding common performance pitfalls.
Flutter aims to render frames in 16ms or less (60 frames per second). On devices with 120Hz displays, this target drops to 8ms. Each frame consists of:
If either phase exceeds its budget, you'll experience jank - visible stuttering or dropped frames.
1. Avoid Opacity Widget in Animations
The Opacity widget is expensive because it requires rendering the child into an intermediate buffer before applying opacity. For animations:
AnimatedOpacity instead of wrapping widgets in OpacityFadeInImage for image fade transitions2. Optimize AnimatedBuilder Usage
AnimatedBuilder rebuilds its subtree on every animation frame. To minimize work:
child parameter, not inside the builderRepaintBoundary to isolate repainting to specific subtrees3. Avoid Clipping During Animation
Clipping operations (ClipRect, ClipRRect, ClipPath) are expensive because they create new layers. When animating:
ClipRect (fastest) instead of ClipRRect or ClipPath when possible4. Use vsync Properly
The vsync parameter in AnimationController prevents offscreen animations from consuming resources. Always:
SingleTickerProviderStateMixin or TickerProviderStateMixin to your State classthis as the vsync parameter5. Leverage RepaintBoundary
RepaintBoundary creates a separate display list that can be cached and reused. Use it to:
Use Flutter DevTools Performance View to:
Enable performance overlays during development:
MaterialApp(
showPerformanceOverlay: true, // Shows GPU/UI thread times
debugShowCheckedModeBanner: false,
)
The timing and easing of animations dramatically affects how they feel. Flutter provides a rich set of curves through the Curves class.
Common Curves:
Curves.linear - No easing, constant speed (rarely used)Curves.easeIn - Slow start, fast finishCurves.easeOut - Fast start, slow finish (most common)Curves.easeInOut - Slow start and finish, fast middleCurves.elasticOut - Bouncy overshoot effectCurves.bounceOut - Multiple bounces at endCurves.fastOutSlowIn - Material Design standard curvePlatform Conventions:
Curves.fastOutSlowIn or Curves.easeOutCurves.easeInOut or custom curves matching UIKit animationsCustom Curves:
You can create custom curves by extending the Curve class or using Cubic for cubic Bézier curves. This is useful for matching designer specifications or creating unique animation feels.
Physics simulations make animations feel natural by modeling real-world behavior like springs, gravity, and friction.
SpringSimulation is the most common physics-based animation. It uses three parameters:
Use Cases:
Implementation Pattern:
Instead of specifying a duration and curve, you use controller.animateWith(simulation) and the physics engine calculates the motion based on initial velocity and spring properties.
Start Simple: Always begin with implicit animations. Only move to explicit animations when you need features implicit animations don't provide.
Compose Animations: Build complex effects by composing simple animations rather than creating monolithic animation code.
Separate Concerns: Keep animation logic separate from business logic. Use AnimatedBuilder or AnimatedWidget to isolate rebuilds.
Provide Feedback: Use animations to acknowledge user input, show state transitions, and guide attention.
Over-Animation: Not everything needs to animate. Too much motion becomes distracting and slows down the user experience.
Inconsistent Timing: Mixing different animation durations randomly creates a chaotic feel. Establish a timing scale (fast: 150ms, normal: 300ms, slow: 500ms) and stick to it.
Ignoring Platform Conventions: iOS and Android have different animation expectations. Consider using platform-specific curves and timings.
Animating on Every Frame: Calling setState() in addListener() rebuilds your entire widget. Use AnimatedBuilder to isolate rebuilds.
Memory Leaks: Forgetting to dispose AnimationController instances causes memory leaks. Always dispose in the dispose() method.
Animations often need to respond to state changes from your chosen state management solution.
Provider/ChangeNotifier: Trigger animations in response to notifyListeners calls BLoC/Cubit: Start animations when specific states are emitted Riverpod: Use providers to trigger animation controller methods GetX: Integrate animations with reactive state updates
The key is separating what changes (state) from how it changes (animation). State management determines when to animate; the animation system handles how.
Testing animations requires special consideration:
Widget Tests: Use WidgetTester.pumpAndSettle() to wait for animations to complete, or pump(duration) to advance by a specific time.
Unit Tests: Test animation controllers and tweens independently of widgets.
Integration Tests: Use tester.pump() in a loop to verify animation behavior over time.
Golden Tests: Capture snapshots at different animation stages to verify visual appearance.
AnimatedContainer, AnimatedOpacity, and TweenAnimationBuilderAnimationController, Tween, and AnimatedBuilderSpringSimulation for natural motionSee the reference documentation for detailed implementation guides:
Flutter's animation system provides the tools to create everything from subtle UI polish to complex, interactive motion experiences. By understanding the spectrum from implicit to explicit animations, leveraging physics for natural motion, and following performance best practices, you can build applications that feel fluid, responsive, and delightful to use.
Remember: the best animations are often the ones users don't consciously notice - they just make the interface feel right.