Flutter导航报错:跳转至V页面时触发空检查运算符使用错误
问题分析与修复
错误原因
- 点击"Next"按钮时先执行
Navigator.pop(context)关闭第一个底部弹窗,此时传入aboutnoteorfolder的context已失效,调用Navigator.of(context)会返回null,触发空检查错误。 AnimationController的vsync参数传入Navigator.of(context)是错误用法——NavigatorState并不实现TickerProvider接口,无法作为动画的同步提供者。
修复方案
- 将
MyHomePage改为StatefulWidget,混入SingleTickerProviderStateMixin以提供合法的TickerProvider。 - 调整
aboutnoteorfolder函数,新增TickerProvider参数用于初始化AnimationController。 - 调用
aboutnoteorfolder时,使用页面自身的context而非弹窗的失效context,并传入当前State作为vsync。 - 确保导航逻辑中使用有效的
context。
修复后的完整代码
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } // 改为StatefulWidget并混入SingleTickerProviderStateMixin class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme!.primary, title: Text(widget.title), ), body: const Center( child: Text('You have pushed the button this many times:'), ), floatingActionButton: FloatingActionButton( onPressed: () { _showModalBottomSheet(context); }, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } void _showModalBottomSheet(BuildContext context) { showModalBottomSheet( context: context, builder: (BuildContext sheetContext) { return Container( height: 200, color: Colors.white, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ const Text( 'Modal Bottom Sheet', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 20), ElevatedButton( onPressed: () { Navigator.pop(sheetContext); // 获取页面的State,用于提供vsync final pageState = context.findAncestorStateOfType<_MyHomePageState>()!; aboutnoteorfolder( context, // 使用页面的context而非弹窗的context vsync: pageState, arrowoperation: () { Navigator.push(context, MaterialPageRoute( builder: (context) { return const V(); }, )); }, ); }, child: const Text('Next'), ), ], ), ), ); }, ); } // 新增vsync参数,接收TickerProvider void aboutnoteorfolder( BuildContext context, { required TickerProvider vsync, required Function() arrowoperation, }) { final AnimationController controller = AnimationController( vsync: vsync, // 使用传入的TickerProvider reverseDuration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 700), ); showModalBottomSheet( elevation: 0, transitionAnimationController: controller, useSafeArea: true, isScrollControlled: true, backgroundColor: Colors.transparent, barrierColor: const Color.fromARGB(90, 0, 0, 0), context: context, builder: (context) { return Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).size.width * 0.02), child: GestureDetector( onTap: arrowoperation, child: Container( width: MediaQuery.of(context).size.width * .955, height: MediaQuery.of(context).size.width * .65, decoration: BoxDecoration( color: const Color.fromARGB(255, 0, 128, 255), border: Border.all( width: MediaQuery.of(context).size.width * 0.0030, color: const Color.fromARGB(120, 255, 255, 255), ), borderRadius: BorderRadius.all(Radius.circular( MediaQuery.of(context).size.width * 0.11, )), ), child: const Center( child: Text("Navigate"), ), ), )); }); } class V extends StatelessWidget { const V({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Scaffold( body: Center(child: Text("V Page")), ); } }
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

