62 lines
1.6 KiB
Dart
62 lines
1.6 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
|
||
|
|
class ScoreText extends StatefulWidget {
|
||
|
|
final int value;
|
||
|
|
final TextStyle? style;
|
||
|
|
|
||
|
|
const ScoreText({super.key, required this.value, this.style});
|
||
|
|
|
||
|
|
@override
|
||
|
|
State<ScoreText> createState() => _ScoreTextState();
|
||
|
|
}
|
||
|
|
|
||
|
|
class _ScoreTextState extends State<ScoreText>
|
||
|
|
with SingleTickerProviderStateMixin {
|
||
|
|
late final AnimationController _controller;
|
||
|
|
late Animation<double> _scale;
|
||
|
|
int _prev = 0;
|
||
|
|
|
||
|
|
@override
|
||
|
|
void initState() {
|
||
|
|
super.initState();
|
||
|
|
_prev = widget.value;
|
||
|
|
_controller = AnimationController(
|
||
|
|
vsync: this,
|
||
|
|
duration: const Duration(milliseconds: 210),
|
||
|
|
);
|
||
|
|
_scale = const AlwaysStoppedAnimation(1.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void didUpdateWidget(covariant ScoreText oldWidget) {
|
||
|
|
super.didUpdateWidget(oldWidget);
|
||
|
|
if (widget.value == _prev) return;
|
||
|
|
final begin = widget.value > _prev ? 1.12 : 0.88;
|
||
|
|
_prev = widget.value;
|
||
|
|
_scale = TweenSequence<double>([
|
||
|
|
TweenSequenceItem(tween: Tween(begin: 1.0, end: begin), weight: 90),
|
||
|
|
TweenSequenceItem(tween: Tween(begin: begin, end: 1.0), weight: 120),
|
||
|
|
]).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
|
||
|
|
_controller
|
||
|
|
..reset()
|
||
|
|
..forward();
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void dispose() {
|
||
|
|
_controller.dispose();
|
||
|
|
super.dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
return AnimatedBuilder(
|
||
|
|
animation: _controller,
|
||
|
|
builder: (context, child) {
|
||
|
|
return Transform.scale(scale: _scale.value, child: child);
|
||
|
|
},
|
||
|
|
child: Text('${widget.value}', style: widget.style),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|