slot_machine_effect 0.0.2
slot_machine_effect: ^0.0.2 copied to clipboard
A slot machine reel for Flutter. Spins up, drifts to a stop on the value you ask for, and rocks into place with a small bounce.
example/lib/main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:slot_machine_effect/slot_machine_effect.dart';
void main() => runApp(const ExampleApp());
/// Index of the blank face the reel parks on before the first spin.
const _blank = 10;
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Slot Machine Effect',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const SlotMachineDemoPage(),
);
}
}
class SlotMachineDemoPage extends StatefulWidget {
const SlotMachineDemoPage({super.key});
@override
State<SlotMachineDemoPage> createState() => _SlotMachineDemoPageState();
}
class _SlotMachineDemoPageState extends State<SlotMachineDemoPage> {
final _random = Random();
int _target = 0;
bool _spinning = false;
bool _spunOnce = false;
void _spin() {
setState(() {
// A spin is triggered by `target` changing, so keep drawing until we
// get a different value — otherwise a repeat would do nothing.
int next;
do {
next = _random.nextInt(10);
} while (next == _target);
_target = next;
_spunOnce = true;
});
}
String get _status {
if (_spinning) return 'Spinning to $_target…';
return _spunOnce ? 'Landed on $_target' : 'Tap spin to start';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Slot Machine Effect')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SlotMachineReel(
height: 125,
width: 300,
// 0-9 plus a blank face, which the reel shows until the first
// spin. Without a placeholder it would rest on `target`.
itemCount: 11,
placeholder: _blank,
target: _target,
bounceDuration: const Duration(milliseconds: 888),
onSpinStart: () => setState(() => _spinning = true),
onSettled: () => setState(() => _spinning = false),
itemBuilder: (e) => Container(
margin: const EdgeInsets.symmetric(vertical: 10),
height: 118.96,
width: 241,
alignment: Alignment.center,
decoration: const BoxDecoration(color: Colors.blue),
child: Text(
e == _blank ? '?' : '$e',
style: Theme.of(context).primaryTextTheme.headlineLarge
?.copyWith(color: Colors.white),
),
),
),
const SizedBox(height: 24),
Text(_status),
const SizedBox(height: 12),
ElevatedButton(
onPressed: _spinning ? null : _spin,
child: const Text('Spin'),
),
],
),
),
);
}
}