63 lines
1.5 KiB
Dart
63 lines
1.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Ícone de navegação que dá um pequeno "pulo" (scale bounce) sempre que
|
|
/// passa a ficar selecionado, para reforçar o feedback de toque na
|
|
/// bottom navigation bar.
|
|
class AnimatedNavIcon extends StatefulWidget {
|
|
const AnimatedNavIcon({
|
|
super.key,
|
|
required this.icon,
|
|
required this.selected,
|
|
});
|
|
|
|
final IconData icon;
|
|
final bool selected;
|
|
|
|
@override
|
|
State<AnimatedNavIcon> createState() => _AnimatedNavIconState();
|
|
}
|
|
|
|
class _AnimatedNavIconState extends State<AnimatedNavIcon>
|
|
with SingleTickerProviderStateMixin {
|
|
late final AnimationController _controller = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 320),
|
|
);
|
|
late final Animation<double> _bounce = TweenSequence<double>([
|
|
TweenSequenceItem(
|
|
tween: Tween(begin: 1.0, end: 1.35).chain(
|
|
CurveTween(curve: Curves.easeOut),
|
|
),
|
|
weight: 40,
|
|
),
|
|
TweenSequenceItem(
|
|
tween: Tween(begin: 1.35, end: 1.0).chain(
|
|
CurveTween(curve: Curves.easeOutBack),
|
|
),
|
|
weight: 60,
|
|
),
|
|
]).animate(_controller);
|
|
|
|
@override
|
|
void didUpdateWidget(covariant AnimatedNavIcon oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (widget.selected && !oldWidget.selected) {
|
|
_controller.forward(from: 0);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ScaleTransition(
|
|
scale: _bounce,
|
|
child: Icon(widget.icon),
|
|
);
|
|
}
|
|
}
|