swift_animations 3.0.0
swift_animations: ^3.0.0 copied to clipboard
SwiftUI-like declarative animations for Flutter. Zero boilerplate - no controllers, no ticker providers required! Works on all platforms.
Swift Animations #
SwiftUI-like declarative animations for Flutter. Zero boilerplate - no controllers, no ticker providers required!
Installation #
dependencies:
swift_animations: ^3.0.0
Quick Start #
import 'package:swift_animations/swift_animations.dart';
Container(
width: 100,
height: 100,
color: Colors.blue,
)
.animate()
.fadeIn()
.scale(1.2)
.duration(500.ms)
Features #
Transformations #
.scale(value)- Scale uniformly.scaleX(value)- Scale on X axis.scaleY(value)- Scale on Y axis.rotate(degrees)- Rotate by degrees
Opacity #
.fadeIn()- Fade from 0 to 1.fadeOut()- Fade from 1 to 0.opacity(value)- Custom opacity (0.0 to 1.0)
Slides #
.slideX(value)- Slide on X axis.slideY(value)- Slide on Y axis.slideInTop()- Slide in from top.slideInBottom()- Slide in from bottom.slideInLeft()- Slide in from left.slideInRight()- Slide in from right
Special Effects #
.bounce()- Bounce animation curve.pulse()- Pulse animation curve.fadeInScale(value)- Combined fade and scale
Extra Effects (blur, shimmer, flip, shake, elevation, color) #
.blur([sigma])- Animate blur (0 → sigma).shimmer()- Shimmer/sweep loading effect.flipX()/.flipY()- 3D card flip.shake()- Shake effect.elevation([value])- Material elevation shadow.saturate([end])- Color saturation (0 = grayscale, 1 = normal).tint(color, [amount])- Color tint overlay
Spring Physics #
.spring(mass, stiffness, damping, initialVelocity)- Custom spring.springIOS()- iOS-style snappy spring.springGentle()- Gentle spring with smooth bounce.springBouncy()- Bouncy spring with high bounce
Configuration #
.duration(value)- Animation duration (supports500.ms,0.5.s,5.m, orDuration).delay(value)- Animation delay.curve(curve)- Custom animation curve.repeat(reverse: bool)- Infinite repeat.repeatCount(count, reverse: bool)- Repeat specific times.persist()- Keep animation state on rebuild
Align, path, then, target, callbacks #
.align({begin, end})- Animate between two alignments (default: topCenter → center).followPath(path)- Move child along aPath(progress 0–1).then({delay})- Add delay so effective delay = delay + thenDelay (sequencing).target(targetNotifier)- Animate to value 0–1 whenValueListenable<double>changes (like AnimatedOpacity).onPlay(callback)- Called when animation starts (after delay).onComplete(callback)- Called when animation completes.callbackAt(at, callback)- Fire callback once when progress crossesat(0–1).listen(listener)- Listener called each frame with current value (0–1)
Custom, toggle, crossfade, swap, shader #
.custom(builder)- Custom widget builder(context, value, child).toggle(at, builder)- At progressat, builder gets(context, value >= at, child).crossfade(builder)- Crossfade to widget from builder (opacity 1-value on child, value on builder()).swap(at, builder)- When progress >=at, replace withbuilder(child).shader(fragmentShader, {uniformIndex})- ApplyFragmentShader; uniform at index set to value 0–1
List stagger #
[widget1, widget2, ...].animate(interval: 200.ms)- Same chain API; each child gets delay = index × interval.- Example:
[A, B, C].animate(interval: 200.ms).fadeIn().slideInBottom()
Adapters (drive animation from scroll or value) #
.animate(drive: myValueListenable)- Progress 0–1 from aValueListenable<double>(e.g. scroll, slider).- Use with
ValueNotifier<double>or anyValueListenable<double>.
Shared effect presets (design system) #
SwiftEffects.entrance(child)- Fade in + slide from bottomSwiftEffects.cardReveal(child)- Fade in + scaleSwiftEffects.slideFromRight(child)- Fade in + slide from rightSwiftEffects.springEntrance(child)- Spring-based entranceSwiftEffects.listEntrance(children, {interval})- Staggered list with entrance
Gesture Extensions #
.sGestureDetector()- Liquid tap effects with spring physicsonPressed- Tap callbackonLongPress- Long press callbackscaleOnPress- Scale amount on tap (default: 1.1)longPressDuration- Long press duration (default: 500ms)autoScaleBySize- Auto-scale based on widget sizestretchSensitivity- Stretch effect sensitivitytranslateSensitivity- Translation sensitivity
Navigation Animations #
Platform-specific navigation animations with a fluent API:
Available Navigation Methods:
swift.push(route)- Push a new routeswift.pushReplacement(route)- Replace current routeswift.pushRoute(route)- Push a route objectswift.pushNamed(routeName)- Push a named routeswift.pushReplacementNamed(routeName)- Replace with named routeswift.pushNamedAndRemoveUntil(routeName, predicate)- Push named route and remove untilswift.pushAndRemoveUntil(route, predicate)- Push route and remove until
Configuration:
.ios()- Use iOS-style slide transition (from right).android()- Use Android-style fade + slide up transition.web()- Use web-style fade transition.duration(milliseconds)- Animation duration (int or Duration).curve(curve)- Animation curve (e.g.,Curves.easeInOut).go(context)- Execute navigation
Examples #
Basic Animation #
Container(
width: 100,
height: 100,
color: Colors.blue,
)
.animate()
.fadeIn()
.scale(1.5)
Spring Animation #
Container(
width: 100,
height: 100,
color: Colors.purple,
)
.animate()
.fadeIn()
.springIOS()
Gesture Detector #
Container(
width: 100,
height: 100,
color: Colors.blue,
)
.sGestureDetector(
onPressed: () => print('Tapped'),
onLongPress: () => print('Long pressed'),
)
Complex Animation #
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: Colors.purple,
borderRadius: BorderRadius.circular(20),
),
)
.animate()
.fadeIn()
.scale(1.2)
.slideInBottom()
.rotate(180)
.duration(1.5.s)
.curve(Curves.easeInOut)
.repeat(reverse: true)
Duration Shorthand #
.animate().duration(500.ms) // 500 milliseconds
.animate().duration(0.5.s) // 0.5 seconds
.animate().duration(5.m) // 5 minutes
.animate().duration(".500ms") // String format
Navigation Animations #
Basic Push Navigation
// iOS-style navigation
swift.push(NextPage())
.ios()
.duration(500)
.curve(Curves.easeInOut)
.go(context);
// Android-style navigation
swift.push(NextPage())
.android()
.duration(500)
.curve(Curves.easeInOut)
.go(context);
Push Replacement
swift.pushReplacement(HomePage())
.ios()
.duration(300)
.go(context);
Push Named Route
swift.pushNamed('/details')
.android()
.duration(400)
.curve(Curves.easeOut)
.go(context, arguments: {'id': 123});
Push and Remove Until
swift.pushAndRemoveUntil(HomePage(), (route) => false)
.ios()
.duration(500)
.go(context);
Push Named and Remove Until
swift.pushNamedAndRemoveUntil('/home', (route) => false)
.android()
.duration(400)
.go(context);
Push Replacement Named
swift.pushReplacementNamed('/login')
.ios()
.duration(300)
.go(context, result: 'logged_out');
Why Swift Animations? #
- ✅ No mixins needed - Just use
StatefulWidgetorStatelessWidget - ✅ Zero boilerplate - No controller setup or disposal
- ✅ Clean API - Simple chaining like SwiftUI
- ✅ Automatic management - All ticker providers handled internally
- ✅ Visibility-based - Animations start when widgets come into view
- ✅ Scroll-aware - Automatically detects scrolling
- ✅ All platforms - Works on iOS, Android, Web, macOS, Linux, Windows
☕ Support the Project #
Love using Swift Animations? Your support helps me create more amazing plugins, add new features, and keep improving the developer experience!
Your contributions enable me to:
- 🚀 Build more Flutter plugins and packages
- ✨ Add exciting new features and improvements
- 🐛 Fix bugs faster and maintain high quality
- 📚 Create better documentation and examples
- 💡 Explore innovative ideas for the Flutter ecosystem
Every contribution, big or small, makes a difference! Thank you for supporting open-source development! 🙏
License #
MIT License