Flutter中向StatefulWidget传递AnimationController报错求助
问题原因
错误提示的核心是:类的实例成员不能在初始化器中被访问。你当前的widgetList是作为类的成员变量直接初始化的,而_controller是在initState方法中才完成初始化的——初始化器的执行早于initState,这时候_controller还未被赋值,自然无法访问。
解决方案
有三种可行的修改方式,你可以根据需求选择:
方案1:将widgetList改为Getter方法
把widgetList改成一个返回列表的getter,这样每次访问时才会构建列表,此时_controller已经完成初始化:
class _DashboardState extends State<Dashboard> with SingleTickerProviderStateMixin { late AnimationController _controller; @override void initState() { _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 150)); _controller.forward(); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } // 改为Getter方法 List<Widget> get widgetList => [ DashboardView(), CallLogs( animationController: _controller, ), ContactLogs(), UserProfile() ]; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: widgetList[context.watch<NavigationIndex>().index], ), bottomNavigationBar: const BottomNavigator(), ); } }
方案2:在initState中初始化widgetList
既然initState是_controller初始化完成后执行的,我们可以把widgetList的初始化移到这里:
class _DashboardState extends State<Dashboard> with SingleTickerProviderStateMixin { late AnimationController _controller; late List<Widget> widgetList; // 只声明,不初始化 @override void initState() { _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 150)); _controller.forward(); // 在这里初始化widgetList widgetList = [ DashboardView(), CallLogs( animationController: _controller, ), ContactLogs(), UserProfile() ]; super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: widgetList[context.watch<NavigationIndex>().index], ), bottomNavigationBar: const BottomNavigator(), ); } }
方案3:在build方法中按需构建Widget
如果你的页面Widget比较轻量,也可以直接在build时根据当前索引创建对应的Widget,避免提前存储列表:
class _DashboardState extends State<Dashboard> with SingleTickerProviderStateMixin { late AnimationController _controller; @override void initState() { _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 150)); _controller.forward(); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final currentIndex = context.watch<NavigationIndex>().index; // 监听索引变化,触发动画重置 WidgetsBinding.instance.addPostFrameCallback((_) { if (_controller.isCompleted) { _controller.reverse().then((_) => _controller.forward()); } }); return Scaffold( body: Center( child: _buildCurrentPage(currentIndex), ), bottomNavigationBar: const BottomNavigator(), ); } Widget _buildCurrentPage(int index) { switch(index) { case 0: return DashboardView(); case 1: return CallLogs(animationController: _controller); case 2: return ContactLogs(); case 3: return UserProfile(); default: return const SizedBox(); } } }
额外优化:实现页面切换动画
针对你想要的底部导航切换动画需求,在方案3的基础上,你可以给页面添加过渡动画,比如淡入淡出效果:
修改_buildCurrentPage方法:
Widget _buildCurrentPage(int index) { Widget page; switch(index) { case 0: page = DashboardView(); break; case 1: page = CallLogs(animationController: _controller); break; case 2: page = ContactLogs(); break; case 3: page = UserProfile(); break; default: page = const SizedBox(); } return FadeTransition( opacity: _controller, child: page, ); }
这样每次切换底部导航时,页面会呈现淡入淡出的过渡动画。
内容的提问来源于stack exchange,提问作者Biswas Sampad
相关产品推荐
相关产品推荐

