Utilizei um mixin para separar a minha tela do meu AnimationController, a fim de deixar o meu Widget mais "limpo" e permitir a reutilização dele em outras telas.
Inicialmente, criei um mixin:
import 'package:flutter/material.dart';
mixin ScaleAnimationMixin<T extends StatefulWidget> on State<T> {
late AnimationController animationController;
late Animation<double> scaleAnimation;
TickerProvider get tickerProvider => this as TickerProvider;
@override
void initState() {
super.initState();
animationController = AnimationController(
vsync: tickerProvider,
duration: const Duration(
milliseconds: 1500,
),
)..repeat(
reverse: true,
);
final CurvedAnimation curvedAnimation = CurvedAnimation(
parent: animationController,
curve: Curves.easeInOutSine,
);
scaleAnimation = Tween<double>(
begin: 0.8,
end: 1,
).animate(
curvedAnimation,
);
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
}
Depois eu apenas importei ele e o SingleTickerProviderStateMixin
no State
do meu StatefulWidget
. O SingleTickerProviderStateMixin
serve para que tenha acesso ao this
do vsync
no AnimationController
. Para usar a animação, no campo scale
do ScaleTransition
passei o scaleAnimation
do mixin
:
class _CategoryComponentState extends State<CategoryComponent>
with ScaleAnimationMixin, SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Container(
width: 160,
height: 155,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: ThemeColors.iconColor,
width: 3,
),
boxShadow: const [
BoxShadow(
color: Color.fromARGB(29, 3, 101, 140),
offset: Offset(-5, -5),
spreadRadius: 5,
blurRadius: 5,
),
BoxShadow(
color: Color.fromARGB(29, 3, 101, 140),
offset: Offset(5, 5),
spreadRadius: 5,
blurRadius: 5,
)
],
),
child: Ink(
child: InkWell(
borderRadius: BorderRadius.circular(15),
onTap: () {
context.read<HomeCubit>().changeSelectedCategory(
category: widget.category,
);
Navigator.of(context).pushNamed(
RoutesEnum.entries.route,
arguments: {
'isFavorite': false,
},
);
},
child: widget.isHighlight
? ScaleTransition(
scale: scaleAnimation,
child: Center(
child: Image.asset(
'${CategoriesConsts.imagePath}${widget.category.name}.png',
height: 80,
fit: BoxFit.fitHeight,
),
),
)
: Center(
child: Image.asset(
'${CategoriesConsts.imagePath}${widget.category.name}.png',
height: 80,
fit: BoxFit.fitHeight,
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 8,
),
child: Text(
widget.category.text,
style: Theme.of(context).textTheme.titleSmall,
),
),
],
);
}
}