所以我在和烦人的问题作斗争。我想同时运行2个动画,但如果没有:
animationController.addListener(() {
setState(() {});
});
这让一切都变得波涛汹涌,我想要根除这一点。
当我在两个动画控制器中删除setstate
并运行此函数时:
void animateButton() {
if (_forward) {
animationController.reverse();
animationController2.reverse();
_forward = false;
} else {
animationController.forward();
animationController2.forward();
_forward = true;
}
}
它只运行第一个动画控制器,而不运行第二个。动画是简单的tween,彼此相反,所以我想做一些东西,用一个tween,对于第二个属性,我做一些反函数,但我想不出任何解,所以它实际上是可行的。也许我错过了一些简单的东西。
以下是我的完整代码:
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),
]),
),
]);
}
}
如有任何帮助,将不胜感激。我在flutter中学习了交错动画
,但是我需要两个动画同时运行,而不需要setstate
。因此我在网上没有找到任何东西,所以我在这里提出问题。提前谢谢你。
好吧,我解决了,我想需要statefulwidget
,它更新动画的每一步,或者可能是我想象的事情,现在工作的代码,没有结巴。
我使用了@Simon Pot的建议,在此基础上,我将widget包装到fadeTransition
中
代码如下:
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),
]),
),
]);
}
}
阅读本文的第一部分,它将解决您的查询以及为什么不应该对自定义动画使用setState的原因。
https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-F2DD9873B8FC
您在这里所做的基本工作是在每次调用小部件时不使用setState并重新构建整个小部件,而是删除其中的侦听器和setState。
然后在AnimatedBuilder中包装to be animated小部件,并将动画控制器作为参数传递到其中。现在,如果您仔细观察的话,它也有builder和child参数。
将小部件的部分放置在子小部件中,在整个动画中不会被更改。(例如:如果您试图对容器的位置进行动画化,那么您可以将整个容器小部件放置在子参数中,因为在动画化过程中,容器小部件中的内容不会被更新。
这不会在每次更新动画框架时重建子小部件,而不是对整个小部件进行动画,从而生成更平滑的动画。
小部件的其余部分将受到动画控制器值变化的影响,应该将其放置在构建器函数中,该函数将提供动画控制器的新值和刚刚初始化的子小部件。
有关AnimatedBuilder小部件的实现,请参阅本文。