flutter-animation — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited flutter-animation (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Manage Flutter animations using the core typed Animation system. Do not manually calculate frames; rely on the framework's ticker and interpolation classes.
Animation<T>: Treat this as an abstract representation of a value that changes over time. It holds state(completed, dismissed) and notifies listeners, but knows nothing about the UI.
AnimationController: Instantiate this to drive the animation. It generates values (typically 0.0 to 1.0) tied tothe screen refresh rate. Always provide a vsync (usually via SingleTickerProviderStateMixin) to prevent offscreen resource consumption. Always dispose() controllers to prevent memory leaks.
Tween<T>: Define a stateless mapping from an input range (usually 0.0-1.0) to an output type (e.g., Color,Offset, double). Chain tweens with curves using .animate().
Curve: Apply non-linear timing (e.g., Curves.easeIn, Curves.bounceOut) to an animation using aCurvedAnimation or CurveTween.
Apply conditional logic to select the correct animation approach:
AnimatedContainer, AnimatedOpacity, TweenAnimationBuilder).
Animations (e.g., AnimationController with AnimatedBuilder or AnimatedWidget).
SpringSimulation).
Tweens driven by asingle AnimationController using Interval curves).
#### Implementing Implicit Animations
Use this workflow for "fire-and-forget" state-driven animations.
Container) with its animated counterpart (e.g., AnimatedContainer).duration property.curve property for non-linear motion.setState() call.#### Implementing Explicit Animations
Use this workflow when you need granular control over the animation lifecycle.
SingleTickerProviderStateMixin (or TickerProviderStateMixin for multiple controllers) to the Stateclass.
AnimationController in initState(), providing vsync: this and a duration.Tween and chain it to the controller using .animate().AnimatedBuilder (preferred for complex trees) or subclass AnimatedWidget.Animation object to the AnimatedBuilder's animation property.controller.forward(), controller.reverse(), or controller.repeat().controller.dispose() in the dispose() method.dispose() is called.#### Implementing Hero Transitions
Use this workflow to fly a widget between two routes.
Hero widget.tag to the source Hero.Hero widget.tag to the destination Hero.Hero widgets are visually similar to prevent jarring jumps.Navigator.#### Implementing Physics-Based Animations
Use this workflow for gesture-driven, natural motion.
AnimationController (do not set a fixed duration).GestureDetector (e.g., onPanEnd providing DragEndDetails).SpringSimulation with mass, stiffness, damping, and the calculated velocity.controller.animateWith(simulation).<details> <summary><b>Example: Explicit Animation (Staggered with AnimatedBuilder)</b></summary>
class StaggeredAnimationDemo extends StatefulWidget {
const StaggeredAnimationDemo({super.key});
@override
State<StaggeredAnimationDemo> createState() => _StaggeredAnimationDemoState();
}
class _StaggeredAnimationDemoState extends State<StaggeredAnimationDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _widthAnimation;
late Animation<Color?> _colorAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
// Staggered width animation (0.0 to 0.5 interval)
_widthAnimation = Tween<double>(begin: 50.0, end: 200.0).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.0, 0.5, curve: Curves.easeIn),
),
);
// Staggered color animation (0.5 to 1.0 interval)
_colorAnimation = ColorTween(begin: Colors.blue, end: Colors.red).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.5, 1.0, curve: Curves.easeOut),
),
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose(); // CRITICAL: Prevent memory leaks
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: _widthAnimation.value,
height: 50.0,
color: _colorAnimation.value,
);
},
);
}
}</details>
<details> <summary><b>Example: Custom Page Route Transition</b></summary>
Route createCustomRoute(Widget destination) {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => destination,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 1.0); // Start from bottom
const end = Offset.zero;
const curve = Curves.easeOut;
final tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
final offsetAnimation = animation.drive(tween);
return SlideTransition(
position: offsetAnimation,
child: child,
);
},
);
}
// Usage: Navigator.of(context).push(createCustomRoute(const NextPage()));</details>
In widget tests, never pumpAndSettle blindly when an animation never settles (e.g., a repeat() loop). Advance the clock explicitly with await tester.pump(duration) to step to a known frame, or await tester.pumpAndSettle() for finite animations, then assert the intermediate or final widget state. See the flutter-testing-apps skill.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.