Flutter:如何用 Provider 播放动画?
Posted
技术标签:
【中文标题】Flutter:如何用 Provider 播放动画?【英文标题】:Flutter: how to play animation with Provider? 【发布时间】:2020-02-28 21:04:46 【问题描述】:我在 Flutter 演示中使用 Provider 来管理状态。
我想为我的小部件设置动画,但似乎 AnimateController 需要一个来自有状态小部件状态的同步参数。
据我所知,不建议将 Provider 与有状态小部件一起使用。
我可以用Provider管理AnimationController吗?
或者必须同时使用 Provider 和 stateful widget?
【问题讨论】:
动画属于 UI,而不是状态。您需要为动画控制器提供一个 Ticker。您可以使用 SingleTickerProviderStateMixin 来避免手动创建它。 api.flutter.dev/flutter/widgets/… @RicardoMarkiewicz 如果我想从同一个父母的不同孩子触发动画怎么办 @RicardoMarkiewicz 但我们都同意状态定义 UI?我认为 Javan 想知道当小部件树被破坏时如何在状态变化时制作漂亮的动画。 Provider 很容易处理,但是状态变化时小部件的即时切换很奇怪。你如何解决这个问题?假设你推送登录,应用程序开始登录,然后切换到下载配置文件,下载这个和那个,最后看到最终的登录界面? 您的动画控制器应该在 UI 部分,而不是在状态类中,因为动画不是您的应用程序状态的一部分(例如,您的用户是否已登录?)而是 UI 瞬态状态的一部分(状态当您离开该屏幕时会迷路)。你需要使用 boh Provider 和 StatefulWidget,你可以使用 AnimatedWidget,你可以使用 FlutterHooks,但永远不要从你的状态/模式类管理你的动画。 【参考方案1】:我可以用Provider管理AnimationController吗?
或者必须同时使用 Provider 和 stateful widget?
我不知道这是否是最好的方法,但我是这样做的:
我在有状态小部件中使用didUpdateWidget。我将值从提供者传递给父级,并在子级中定义的didUpdateWidget
方法中触发动画。 didUpdateWidget
当我通知听众提供者发生变化时自动触发。
class MyWidget extends StatefulWidget
final String valueFromProvider;
MyWidget(this.valueFromProvider);
@override
_MyWidgetState createState() => _MyWidgetState();
class _MyWidgetState extends State<MyWidget> with TickerProviderStateMixin
@override
void didUpdateWidget(MyWidget oldWidget)
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
if (oldWidget.valueFromProvider == "whatever you want" &&
widget.valueFromProvider == "what you want that changed")
// trigger animations methods here
// here all the animations methods,dispose method, etc.
@override
Widget build(BuildContext context)
return Container();
【讨论】:
【参考方案2】:如果你想在 StatelessWidget 中创建 AnimationController,你必须在 StatelessWidget 的构造函数中传递 TickerProviderStateMixin,看看我的示例代码:
import 'package:flutter/material.dart';
main()
runApp(TestyApp());
class TestyApp extends StatefulWidget
@override
_TestyAppState createState() => _TestyAppState();
class _TestyAppState extends State<TestyApp> with TickerProviderStateMixin
@override
Widget build(BuildContext context)
return MaterialApp(
home: TestAnimationInStatelessWidget(
tickerProviderStateMixin: this,
),
);
class TestAnimationInStatelessWidget extends StatelessWidget
final TickerProviderStateMixin tickerProviderStateMixin;
const TestAnimationInStatelessWidget(
Key key, @required this.tickerProviderStateMixin)
: assert(tickerProviderStateMixin != null),
super(key: key);
@override
Widget build(BuildContext context)
var _animationController = AnimationController(
vsync: tickerProviderStateMixin, duration: Duration(seconds: 1));
var _animation = Tween<double>(begin: 0, end: 2).animate(CurvedAnimation(
parent: _animationController, curve: Curves.easeInOut));
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RotationTransition(
turns: _animation,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.blueGrey,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
),
),
SizedBox(
height: 30,
),
RaisedButton(
onPressed: ()
_animationController.reset();
_animationController.forward();
,
child: Text("Start Animation"),
)
],
),
),
);
【讨论】:
在您的示例中,您使用的是有状态小部件。【参考方案3】:我做了一个解决方法,覆盖了 didChangeDependencies 方法,该方法会在出现提示时触发 AnimationController.forward。
我从这个 *** 线程 link 得到这个想法
@override
void didChangeDependencies()
super.didChangeDependencies();
var result = Provider.of<Home>(context).notification;
if (result == "Play")
_controller.forward();
但是,这只是一种解决方法,我仍在寻找一种更有效的方法来管理它(使用 Provider / 或其他解决方案,在另一个不相关的小部件中的有状态小部件中启动/停止动画)。
【讨论】:
以上是关于Flutter:如何用 Provider 播放动画?的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 中使用 Provider 更新和动画化 AnimatedList
如何为 Flutter SliverList 中的元素设置动画?
Flutter Provider:为啥在调用 Provider.of<Widget>(context) 时会出现此错误,如 tihis: