flutter_scratch_card 2.0.0
flutter_scratch_card: ^2.0.0 copied to clipboard
A production-ready, highly customizable Flutter scratch card SDK with ImageProvider overlays, themes, brushes, haptics, multi-area scratching, persistence, and accessibility.
flutter_scratch_card #
A production-ready, highly customizable Flutter scratch card SDK.

Features #
- ImageProvider overlays —
NetworkImage,AssetImage,MemoryImage, with loading/error fallback - Configurable brushes — size, softness, hardness, spacing, shapes (circle, square, rounded rect, custom)
- Reveal shapes — rectangle, circle, rounded rectangle, custom path
- Themes — classic, metallic, golden, premium, neon, minimal (fully overridable)
- Callbacks — start / scratch / end / progress / milestone / threshold / complete / reset
- Haptics — throttled light / medium / heavy / selection feedback
- Optional sounds — adapter API (no audio package required)
- Completion effects — fade, scale, glow, confetti, shake (no heavy deps)
- Controller API — reveal, reset (optional animated), pause, resume, progress
- Multi-area scratching — independent regions with per-area completion
- Async / multi rewards — first, random, predefined, or host-loaded
- Accessibility — semantics label/hint + “reveal” action
- Persistence — pluggable
ScratchStateStorage(in-memory built-in) - Performance controls — grid resolution, point caps, progress throttling
- Lottie / GIF celebrations under the scratch layer (optional
lottie)
Installation #
dependencies:
flutter_scratch_card: ^2.0.0
flutter pub get
Basic usage #
ScratchCard(
overlayImage: const AssetImage('assets/scratch.png'),
child: const Text('₹100'),
)
Controller #
final controller = ScratchController();
ScratchCard(
controller: controller,
onComplete: () {},
child: reward,
);
controller.reveal();
controller.reset(animated: true);
controller.pause();
controller.resume();
print(controller.progress);
print(controller.isComplete);
Customization #
ScratchCard(
theme: ScratchCardTheme.premium(),
brush: ScratchBrush.soft(size: 35),
revealShape: ScratchRevealShape.circle(),
overlayImage: const NetworkImage('https://example.com/scratch.png'),
fallbackOverlayImage: const AssetImage('assets/fallback.png'),
haptic: const ScratchHapticConfig(
onScratch: HapticType.light,
onMilestone: HapticType.medium,
onComplete: HapticType.heavy,
),
completion: const ScratchCompletionConfig(
effect: ScratchCompletionEffect.confetti,
),
animation: const ScratchAnimationConfig(
duration: Duration(milliseconds: 500),
curve: Curves.easeOut,
),
child: reward,
)
Callbacks #
ScratchCard(
progressTriggers: const [0.25, 0.5, 0.75],
onScratchStart: () {},
onScratch: (offset) {},
onScratchEnd: () {},
onProgress: (p) {},
onMilestone: (m) {},
onThreshold: () {},
onComplete: () {},
onReset: () {},
child: reward,
)
onComplete fires once until reset(). Auto-reveal and controller.reveal() also trigger it.
Advanced #
Multiple areas #
Areas are laid out in a horizontal row using flex:
ScratchCard(
areas: [
ScratchArea(id: 'left', flex: 1, child: Text('A')),
ScratchArea(id: 'right', flex: 1, child: Text('B')),
],
onAreaComplete: (id) {},
child: const SizedBox.shrink(),
)
Async reward #
ScratchCard(
rewardSelection: ScratchRewardSelection.async,
rewardBuilder: (context) async => Text(await fetchPrize()),
rewardLoadingBuilder: (_) => const CircularProgressIndicator(),
rewardErrorBuilder: (context, error, retry) =>
TextButton(onPressed: retry, child: const Text('Retry')),
child: const SizedBox.shrink(),
)
Persistence #
ScratchCard(
stateKey: 'daily_reward_2026_08_21',
stateStorage: MemoryScratchStateStorage(), // or your SharedPreferences adapter
child: reward,
)
Implement ScratchStateStorage to persist with SharedPreferences, Hive, etc.
Sound (optional) #
class MyPlayer implements ScratchSoundPlayer {
@override
Future<void> playScratch() async { /* audioplayers / just_audio */ }
@override
Future<void> playComplete() async {}
@override
void dispose() {}
}
ScratchCard(
sound: ScratchSoundConfig(enabled: true, player: MyPlayer()),
child: reward,
)
Performance #
- Grid-based progress (configurable resolution)
- Soft cap on scratch points
- Optional progress update throttling
RepaintBoundaryisolation for overlay vs reward layers- Throttled haptics / sounds during drag
performance: ScratchPerformanceConfig.lowEnd(),
Accessibility #
ScratchCard(
semanticLabel: 'Scratch card containing a reward',
semanticHint: 'Scratch to reveal your reward',
child: reward,
)
Semantics also expose a tap/reveal action for users who cannot drag.
API reference #
See the Dart API docs on pub.dev.
Migration (1.x → 2.0) #
See MIGRATION.md.
Breaking highlights:
overlayImageis nowImageProvider?(wasui.Image?)- Use
overlayUiImagefor a decodedui.Image - Prefer
AssetImageover deprecatedoverlayImageAsset
License #
MIT — see LICENSE.