flutter_svga_easyplayer
A Flutter package for parsing and rendering SVGA animations efficiently with powerful EasyPlayer features.
SVGA is a lightweight and powerful animation format used for dynamic UI effects in mobile applications.
๐ Features
โ๏ธ Parse and render SVGA animations in Flutter.
โ๏ธ Load SVGA files from assets and network URLs.
โก Silent background precaching โ hand a list of URLs at startup (or any
screen), they get warmed into the cache, and later playback is instant.
โ๏ธ Intelligent caching system for faster loading and reduced network usage.
โ๏ธ Per-widget cache control: Enable/disable caching and auto-cleanup per player.
โ๏ธ Playback control modes: infinite loop, play once, or repeat N times with completion callbacks.
โ๏ธ Audio Control: Mute/Unmute audio support.
โ๏ธ Supports custom dynamic elements (text, images, animations).
โ๏ธ Optimized playback performance with animation controllers.
โ๏ธ Integrated audio playback within SVGA animations.
โ๏ธ Works on Android & iOS (Web & Desktop support coming soon).
โ๏ธ Easy loop, stop, and seek functions.
๐ Installation
Add flutter_svga_easyplayer to your pubspec.yaml:
dependencies:
flutter_svga_easyplayer: ^0.0.6
Then, install dependencies:
flutter pub get
๐ฌ Basic Usage
โ Playing an SVGA Animation from Assets
import 'package:flutter/material.dart';
import 'package:flutter_svga_easyplayer/flutter_svga_easyplayer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Flutter SVGA Example")),
body: Center(
child: SVGAEasyPlayer(
assetsName: "assets/sample_with_audio.svga",
fit: BoxFit.contain,
),
),
),
);
}
}
๐ Playing SVGA from a Network URL
SVGAEasyPlayer(
resUrl: "https://example.com/sample.svga",
fit: BoxFit.cover,
);
๐ฎ Playback Control Modes (NEW!)
SVGAEasyPlayer now supports three powerful playback modes:
โ Infinite Loop (Default)
SVGAEasyPlayer(
assetsName: "assets/loading.svga",
// loops: null (default) - plays infinitely
)
โ Play Once
SVGAEasyPlayer(
assetsName: "assets/splash.svga",
loops: 0, // Play once then stop
onFinished: () {
print("Animation completed!");
// Navigate to next screen, etc.
},
)
โ Repeat N Times
SVGAEasyPlayer(
assetsName: "assets/celebration.svga",
loops: 3, // Play 4 times total (1 + 3 repeats)
onFinished: () {
print("All repetitions completed!");
},
)
๐ Read the full Playback Modes Guide for detailed examples and use cases.
๐ Audio Control (NEW!)
Control audio playback directly from the widget:
โ Mute Audio
SVGAEasyPlayer(
assetsName: "assets/animation_with_audio.svga",
isMute: true, // Mutes the audio
)
โก Silent Background Precaching (NEW in 0.0.6!)
Pass a list of URLs (or asset paths) and the package silently downloads
and caches them in the background. Later, when a SVGAEasyPlayer is
rendered with the same URL, it plays instantly from the local cache โ
no network round-trip, no loading flash.
The parser already reads from the same cache on playback, so there is nothing extra to wire up at the widget side.
โ
At app startup (inside main())
import 'package:flutter/material.dart';
import 'package:flutter_svga_easyplayer/flutter_svga_easyplayer.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Fire-and-forget: warms the cache silently in the background.
SVGAPrecacheManager.shared.precache(
const [
'https://cdn.example.com/a.svga',
'https://cdn.example.com/b.svga',
'https://cdn.example.com/c.svga',
],
delay: const Duration(seconds: 1), // optional: wait for startup to settle
concurrency: 3, // optional: max parallel downloads
timeout: const Duration(seconds: 15), // optional: per-URL timeout
);
runApp(const MyApp());
}
โ Anywhere else (any screen, any time)
You are not limited to main(). Trigger precache from initState, a
button tap, after login, or whenever your app decides it needs to warm
the cache:
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
void initState() {
super.initState();
// Fire-and-forget: warms the cache for animations this screen will use.
SVGAPrecacheManager.shared.precache(const [
'https://cdn.example.com/home_hero.svga',
'https://cdn.example.com/home_badge.svga',
]);
}
@override
Widget build(BuildContext context) {
// Instant playback the first time it shows โ pre-cached above.
return const SVGAEasyPlayer(
resUrl: 'https://cdn.example.com/home_hero.svga',
);
}
}
โ With progress reporting & result
final result = await SVGAPrecacheManager.shared.precache(
urls,
onProgress: (done, total, url, ok) {
debugPrint('[$done/$total] ${ok ? "OK" : "FAIL"} $url');
},
);
debugPrint('precache result: $result');
// SVGAPrecacheResult(total: 6, completed: 6, hits: 2, fetched: 4, failed: 0, cancelled: false)
โ From bundled assets
SVGAPrecacheManager.shared.precacheAssets(const [
'assets/intro.svga',
'assets/celebration.svga',
]);
โ Cancel an in-flight batch
SVGAPrecacheManager.shared.cancel();
๐ง Why itโs smart
- โ Skip-if-cached โ URLs already in the cache are detected and skipped without any network I/O. Safe to call on every app launch.
- โ Deduplicated โ if two batches request the same URL at the same time, only one download happens.
- โ Fails gracefully โ network errors, asset misses, timeouts or disk errors are swallowed silently; one bad URL never blocks the rest.
- โ
Honours global settings โ respects
SVGACache.shared's enable flag,maxCacheSize, andmaxAge. - โ
Cache key parity โ uses the exact same cache keys as the
parser, so
SVGAEasyPlayer(resUrl: url)automatically hits it.
๐ API at a glance
| Call | What it does |
|---|---|
SVGAPrecacheManager.shared.precache(urls, ...) |
Warm the cache with a list of network URLs. |
SVGAPrecacheManager.shared.precacheAssets(paths, ...) |
Warm the cache with a list of bundled asset paths. |
SVGAPrecacheManager.shared.cancel() |
Stop picking up new items from in-flight batches. |
SVGAPrecacheManager.shared.isRunning |
true while any batch is still running. |
SVGACache.shared.contains(source) |
Cheap async check whether a valid cache entry exists. |
๐พ Cache Control in EasyPlayer (NEW!)
Control caching behavior on a per-widget basis:
โ With Cache (Default - Faster)
SVGAEasyPlayer(
assetsName: "assets/animation.svga",
useCache: true, // default - uses cache for fast loading
)
โ Without Cache (Always Fresh)
SVGAEasyPlayer(
resUrl: "https://api.example.com/dynamic.svga",
useCache: false, // bypass cache, always load fresh
)
โ Auto-Cleanup on Dispose
SVGAEasyPlayer(
assetsName: "assets/one-time.svga",
clearCacheOnDispose: true, // removes from cache when disposed
loops: 0,
onFinished: () => Navigator.pop(),
)
๐ Read the Cache Control Guide for advanced cache management strategies.
๐ญ Advanced Usage: Using SVGAAnimationController
โ Controlling Animation Playback
class MySVGAWidget extends StatefulWidget {
@override
_MySVGAWidgetState createState() => _MySVGAWidgetState();
}
class _MySVGAWidgetState extends State<MySVGAWidget>
with SingleTickerProviderStateMixin {
late SVGAAnimationController _controller;
@override
void initState() {
super.initState();
_controller = SVGAAnimationController(vsync: this);
// Mute audio if needed
_controller.isMute = true;
SVGAParser.shared.decodeFromAssets("assets/sample.svga").then((video) {
_controller.videoItem = video;
_controller.repeat();
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SVGAImage(_controller);
}
}
๐จ Customization & Dynamic Elements
โ Adding Dynamic Text
controller.videoItem!.dynamicItem.setText(
TextPainter(
text: TextSpan(
text: "Hello SVGA!",
style: TextStyle(color: Colors.red, fontSize: 18),
),
textDirection: TextDirection.ltr,
),
"text_layer",
);
โ Replacing an Image Dynamically
controller.videoItem!.dynamicItem.setImageWithUrl(
"https://example.com/new_image.png",
"image_layer",
);
โ Hiding a Layer
controller.videoItem!.dynamicItem.setHidden(true, "layer_to_hide");
๐๏ธ Caching (New!)
Automatic performance optimization with zero breaking changes:
// Caching works automatically - no code changes needed!
final animation = await SVGAParser.shared.decodeFromURL(
"https://example.com/animation.svga"
);
// Optional: Configure cache settings
SVGACache.shared.setMaxCacheSize(50 * 1024 * 1024); // 50MB
SVGACache.shared.setMaxAge(const Duration(days: 3)); // 3 days
// Optional: Manage cache
await SVGACache.shared.clear(); // Clear all cache
final stats = await SVGACache.shared.getStats(); // Get cache info
๐ See CACHE.md for complete caching documentation and examples.
๐ฏ Playback Controls
controller.forward(); // Play once
controller.repeat(); // Loop playback
controller.stop(); // Stop animation
controller.value = 0; // Reset to first frame
๐ Common Issues & Solutions
โ Black Screen when Loading SVGA
โ
Solution: Ensure your svga files are correctly placed inside assets/ and registered in pubspec.yaml.
flutter:
assets:
- assets/sample.svga
โ SVGA Not Loading from Network
โ Solution: Ensure the SVGA file is accessible via HTTPS. Test the URL in a browser.
SVGAEasyPlayer(
resUrl: "https://example.com/sample.svga",
fit: BoxFit.cover,
);
โ Animation Freezes or Doesn't Play
โ
Solution: Use setState after loading SVGA to rebuild the widget.
setState(() {
_controller.videoItem = video;
});
๐ฑ Supported Platforms
| Platform | Supported | Audio Support |
|---|---|---|
| โ Android | โ๏ธ Yes | โ๏ธ Yes |
| โ iOS | โ๏ธ Yes | โ๏ธ Yes |
| โ Linux | โ๏ธ Yes | โ๏ธ Yes |
| โ Web | โ๏ธ Yes | โ No |
| โ macOS | โ๏ธ Yes | โ๏ธ Yes |
| โ Desktop | โ๏ธ Yes | โ๏ธ Yes |
๐ Changelog
See the latest changes in CHANGELOG.md.
๐ License
This package is licensed under the MIT License. See LICENSE for details.
๐ค Contributing
- If you find a bug, report it here.
- Pull requests are welcome! See
CONTRIBUTING.mdfor guidelines.
๐จโ๐ป Authors & Contributors
๐ Core Author
- zamansheikh โ Lead Developer, Maintainer, and Flutter Integration Engineer.
๐ค Contributors
Special thanks to the amazing contributors who improved flutter_svga:
| Contributor | Contribution | GitHub |
|---|---|---|
| wonderkidshihab | Fixed repeated music playback bug (#3) | ๐งฉ |
Want to contribute? Read CONTRIBUTING.md and submit your PR โ weโd love your help!
๐ Enjoy using SVGA animations in your Flutter app! ๐