Created
July 27, 2024 19:39
-
-
Save sma/e028c56804aa612bad8f7639c3fa1397 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(App()); | |
} | |
class App extends StatelessWidget { | |
const App({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
body: Center( | |
child: CountdownWidget(style: TextStyle(fontSize: 256)), | |
), | |
), | |
); | |
} | |
} | |
class CountdownWidget extends StatefulWidget { | |
const CountdownWidget({ | |
super.key, | |
this.initialValue = 9, | |
this.style, | |
this.onEnd, | |
}) : assert(initialValue > 0); | |
final int initialValue; | |
final TextStyle? style; | |
final VoidCallback? onEnd; | |
@override | |
State<CountdownWidget> createState() => _CountdownWidgetState(); | |
} | |
class _CountdownWidgetState extends State<CountdownWidget> with SingleTickerProviderStateMixin { | |
late final AnimationController _controller = AnimationController(vsync: this, duration: const Duration(seconds: 1)); | |
late int _currentValue = widget.initialValue; | |
@override | |
void initState() { | |
super.initState(); | |
_controller.addStatusListener((status) { | |
if (status == AnimationStatus.completed) { | |
setState(() { | |
if (_currentValue > 1) { | |
_currentValue--; | |
_controller.reset(); | |
_controller.forward(); | |
} else { | |
widget.onEnd?.call(); | |
} | |
}); | |
} | |
}); | |
_controller.forward(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
void didUpdateWidget(CountdownWidget oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
_currentValue = widget.initialValue; | |
_controller.reset(); | |
_controller.forward(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return AnimatedBuilder( | |
animation: _controller, | |
builder: (context, child) { | |
final value = 1 - Curves.easeInCubic.transform(_controller.value); | |
return Opacity( | |
opacity: value, | |
child: Transform.scale( | |
scale: value, | |
child: Text( | |
'$_currentValue', | |
style: widget.style ?? Theme.of(context).textTheme.displayLarge, | |
), | |
), | |
); | |
}, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment