Issue
So I am struggling with annoying problem. I want to run 2 animations at the same time and somewhat it does not work without:
animationController.addListener(() {
setState(() {});
});
Which is making everything choppy, which I would like to eradicate.
When I delete setState
in both of my animation controllers and run this function:
void animateButton() {
if (_forward) {
animationController.reverse();
animationController2.reverse();
_forward = false;
} else {
animationController.forward();
animationController2.forward();
_forward = true;
}
}
It runs just the first animation controller, without second one. Animations are simple tweens which are opposite to each other, so I was thinking about doing something which would use one tween and for second property I would do some inverse function, but I can’t think of any solution for this, so it would actually work. Maybe I am missing something simple.
Here is my full code:
class _DetailScreenState extends State<DetailScreenWidget>
with TickerProviderStateMixin {
final GlobalKey<SendWidgetState> _key = GlobalKey();
AnimationController animationController;
Animation<double> tween;
AnimationController animationController2;
Animation<double> tween2;
@override
void initState() {
super.initState();
// FocusScope.of(context).unfocus();
animationController = AnimationController(
vsync: this, duration: Duration(milliseconds: 800));
tween = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.easeOut));
animationController.addListener(() {
setState(() {});
});
animationController2 = AnimationController(
vsync: this, duration: Duration(milliseconds: 800));
tween2 = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(parent: animationController2, curve: Curves.easeOut));
animationController2.addListener(() {
setState(() {});
});
}
void showHideSendView() {
if (_forward) {
animationController.reverse();
animationController2.reverse();
_forward = false;
} else {
animationController.forward();
animationController2.forward();
_key.currentState.initView();
_forward = true;
}
}
void showTransactions() {
setState(() {
showHideSendView();
});
}
Widget build(BuildContext context) {
return Stack(children: [
SafeArea(
child: Stack(children: [
TransactionWidget(
opacity: tween2,
getTransactions: _getTransactions,
),
SizeTransition(
sizeFactor: tween,
axis: Axis.vertical,
axisAlignment: -1,
child: SendWidget(
key:_key,
func: shrinkSendView,
height: tween,
),
),
BalanceCard(
getBalanceFuture: _getBalanceFuture,
onPressSend: showTransactions),
]),
),
]);
}
}
I learned about staggered animation
in flutter, however I need 2 animations to run at the same time without setState
. And for that I didn’t find on the internet anything, so I resort to asking questions here.
Solution
Alright I solved it, I guess there is a need for statefulWidget
which updates on every step of the animation or maybe I am imagine things, now the working code, without stuttering.
I used advice by @Simon Pot and on the top of that I wrapped widget into FadeTransition
Here is the code:
class _DetailScreenState extends State<DetailScreenWidget>
with TickerProviderStateMixin {
final GlobalKey<SendWidgetState> _key = GlobalKey();
AnimationController animationController;
Animation<double> tween;
Animation<double> tween2;
Future _getBalanceFuture;
Future _getTransactions;
bool _forward = false;
@override
void initState() {
super.initState();
animationController = AnimationController(
vsync: this, duration: Duration(milliseconds: 800));
tween2 = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.easeOut));
tween = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.easeOut));
_getBalanceFuture = getBalance();
_getTransactions = _getTranData();
}
void animateButton() {
if (_forward) {
animationController.reverse();
_forward = false;
} else {
animationController.forward();
_key.currentState.initView();
_forward = true;
}
}
void showTransactions() {
animateButton();
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Stack(children: [
SafeArea(
child: Stack(children: [
FadeTransition(
opacity: tween2,
child: TransactionWidget(
getTransactions: _getTransactions,
),
),
SizeTransition(
sizeFactor: tween,
axis: Axis.vertical,
axisAlignment: -1,
child: SendWidget(
key:_key,
func: shrinkSendView,
height: tween,
),
),
BalanceCard(
getBalanceFuture: _getBalanceFuture,
onPressSend: showTransactions),
]),
),
]);
}
}
Answered By – Michal Žídek
Answer Checked By – Mildred Charles (FlutterFixes Admin)