为何同款Bottom Sheet代码他人可用我却无法运行?
问题:Flutter Bottom Sheet无法打开,报错"No MaterialLocalizations found"
问题详情
- 环境版本:Flutter 3.10.2 | Dart 3.0.2 | DevTools 2.23.1
- 现象:调用
showModalBottomSheet时无法打开底部弹窗,控制台抛出报错:I/flutter ( 4269): Another exception was thrown: No MaterialLocalizations found. - 临时解决:将
MaterialApp移到组件树外层后功能恢复正常,但想明确原代码失效的具体原因
原代码如下:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { Widget buildButtonSheet(BuildContext context) { return Container( color: Colors.white, height: 300, child: Center( child: Text('Sheet Opened'), ), ); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Bottom Sheet Example', home: Scaffold( backgroundColor: Colors.black, appBar: AppBar( title: const Text('Bottom Sheet Example'), ), body: Center( child: ElevatedButton( child: const Text('Bottom Sheet'), onPressed: () { showModalBottomSheet( context: context, builder: buildButtonSheet); }, ), ), ), ); } }
失效原因分析
核心问题是调用showModalBottomSheet时使用的context作用域错误:
- 原代码中,
MyApp的build方法直接返回MaterialApp,而触发弹窗时传入的context是_MyAppState的context——这个context属于MyApp组件,它的上层组件树中并没有MaterialApp(因为MaterialApp是当前组件才构建出来的)。 showModalBottomSheet是Material组件库提供的方法,它依赖MaterialApp注入的MaterialLocalizations本地化资源来正常工作。当使用未被MaterialApp包裹的context调用它时,Flutter无法在组件树中找到所需的本地化资源,因此抛出"No MaterialLocalizations found"错误。
而你把MaterialApp移到外层后,触发弹窗时使用的context来自MaterialApp内部的Scaffold组件,这个context的上层存在MaterialApp,可以正确获取到所需的资源,因此弹窗能正常打开。
修正后的代码示例
import 'package:flutter/material.dart'; void main() => runApp(const MaterialApp( title: 'Flutter Bottom Sheet Example', home: MyApp(), )); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { Widget buildButtonSheet(BuildContext context) { return Container( color: Colors.white, height: 300, child: const Center( child: Text('Sheet Opened'), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( title: const Text('Bottom Sheet Example'), ), body: Center( child: ElevatedButton( child: const Text('Bottom Sheet'), onPressed: () { showModalBottomSheet( context: context, builder: buildButtonSheet); }, ), ), ); } }
内容的提问来源于stack exchange,提问作者Im Onforum
相关产品推荐
相关产品推荐

