没有setstate同时出现两个动画
Two animations at the same time without setstate
所以我正在努力解决烦人的问题。我想同时 运行 2 个动画,如果没有:
就无法工作
animationController.addListener(() {
setState(() {});
});
这让一切变得波涛汹涌,我想根除它。
当我删除我的两个动画控制器中的 setState
和 运行 这个函数时:
void animateButton() {
if (_forward) {
animationController.reverse();
animationController2.reverse();
_forward = false;
} else {
animationController.forward();
animationController2.forward();
_forward = true;
}
}
运行只有第一个动画控制器,没有第二个。动画是彼此相反的简单补间动画,所以我正在考虑做一些使用补间动画的事情,然后 属性 我会做一些反函数,但我想不出任何解决方案,所以它实际上会起作用。也许我遗漏了一些简单的东西。
这是我的完整代码:
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 中了解了 staggered animation
,但是我需要 2 个动画同时到 运行 而没有 setState
。为此,我在互联网上没有找到任何东西,所以我求助于在这里提问。
阅读本文的第一部分,它将解决您的疑问以及您不应将 setState 用于自定义动画的原因。
https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-f2dd9873b8fc
你在这里做的基本上不是使用 setState 并在每次调用它时重建整个小部件,而是删除侦听器和其中的 setState。
然后将要动画的小部件包装在 AnimatedBuilder 中,并将动画控制器作为参数传递给它。现在,如果您仔细观察,它也有构建器和子参数。
将您的小部件的部分在整个动画过程中不会更改的子小部件内。 (例如:如果您尝试为容器的位置设置动画,则可以将整个容器小部件放置在子参数中,因为其中的内容在动画期间不会更新。
这不会为整个小部件设置动画,而是不会在您每次更新动画帧时重建子小部件,从而使动画更加流畅。
小部件的其余部分将受到动画控制器值变化的影响,应将其放置在生成器函数中,该函数提供动画控制器的新值和您刚刚初始化的子小部件。
AnimatedBuilder 小部件的实现请参阅文章。
好吧,我解决了,我想需要 statefulWidget
它会在动画的每一步上更新,或者我可能正在想象事情,现在是工作代码,没有口吃。
我使用了@Simon Pot 的建议,最重要的是我将小部件包装到 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),
]),
),
]);
}
}
所以我正在努力解决烦人的问题。我想同时 运行 2 个动画,如果没有:
就无法工作animationController.addListener(() {
setState(() {});
});
这让一切变得波涛汹涌,我想根除它。
当我删除我的两个动画控制器中的 setState
和 运行 这个函数时:
void animateButton() {
if (_forward) {
animationController.reverse();
animationController2.reverse();
_forward = false;
} else {
animationController.forward();
animationController2.forward();
_forward = true;
}
}
运行只有第一个动画控制器,没有第二个。动画是彼此相反的简单补间动画,所以我正在考虑做一些使用补间动画的事情,然后 属性 我会做一些反函数,但我想不出任何解决方案,所以它实际上会起作用。也许我遗漏了一些简单的东西。
这是我的完整代码:
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 中了解了 staggered animation
,但是我需要 2 个动画同时到 运行 而没有 setState
。为此,我在互联网上没有找到任何东西,所以我求助于在这里提问。
阅读本文的第一部分,它将解决您的疑问以及您不应将 setState 用于自定义动画的原因。
https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-f2dd9873b8fc
你在这里做的基本上不是使用 setState 并在每次调用它时重建整个小部件,而是删除侦听器和其中的 setState。
然后将要动画的小部件包装在 AnimatedBuilder 中,并将动画控制器作为参数传递给它。现在,如果您仔细观察,它也有构建器和子参数。
将您的小部件的部分在整个动画过程中不会更改的子小部件内。 (例如:如果您尝试为容器的位置设置动画,则可以将整个容器小部件放置在子参数中,因为其中的内容在动画期间不会更新。
这不会为整个小部件设置动画,而是不会在您每次更新动画帧时重建子小部件,从而使动画更加流畅。
小部件的其余部分将受到动画控制器值变化的影响,应将其放置在生成器函数中,该函数提供动画控制器的新值和您刚刚初始化的子小部件。
AnimatedBuilder 小部件的实现请参阅文章。
好吧,我解决了,我想需要 statefulWidget
它会在动画的每一步上更新,或者我可能正在想象事情,现在是工作代码,没有口吃。
我使用了@Simon Pot 的建议,最重要的是我将小部件包装到 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),
]),
),
]);
}
}