Flutter中showModalBottomSheet()无法显示模态底部弹窗的问题
解决Flutter中模态底部弹窗无法显示的问题
嘿,我瞅见你这代码里的问题啦!问题出在你调用showModalBottomSheet时用的context不对。
问题原因
你当前传递给startInputAction的context是MyApp这个StatefulWidget的上下文,而它属于MaterialApp层级。showModalBottomSheet需要的是包含在Scaffold内部的上下文——因为它依赖于Scaffold关联的Navigator来管理弹窗的展示逻辑,用MaterialApp的context根本找不到对应的导航栈,自然弹不出窗口。
两种修复方案
方案一:用Builder包裹按钮获取正确的Context
在按钮外层套一个Builder组件,它会提供一个属于Scaffold层级的context,把这个context传给startInputAction即可:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { void startInputAction(BuildContext context) { showModalBottomSheet( context: context, builder: (_) { return Container( height: 200, padding: EdgeInsets.all(10), child: Text("Something"), ); }, ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Error Practice Bottom Sheet"), backgroundColor: Colors.purple, ), body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // 添加Builder获取Scaffold层级的context Builder( builder: (scaffoldContext) { return RaisedButton( color: Colors.purple, padding: EdgeInsets.all(20), child: Text("Click here"), onPressed: () => startInputAction(scaffoldContext), ); }, ) ], ), ), ), ); } }
方案二:重构Widget结构,调整MaterialApp的位置
把MaterialApp移到main函数里,让MyApp的build方法直接返回Scaffold,这样_MyAppState的context就属于Scaffold层级了:
import 'package:flutter/material.dart'; void main() => runApp( // 将MaterialApp移到这里作为根组件 MaterialApp( home: MyApp(), ), ); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { void startInputAction(BuildContext context) { showModalBottomSheet( context: context, builder: (_) { return Container( height: 200, padding: EdgeInsets.all(10), child: Text("Something"), ); }, ); } @override Widget build(BuildContext context) { // 直接返回Scaffold,此时context属于Scaffold层级 return Scaffold( appBar: AppBar( title: Text("Error Practice Bottom Sheet"), backgroundColor: Colors.purple, ), body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RaisedButton( color: Colors.purple, padding: EdgeInsets.all(20), child: Text("Click here"), onPressed: () => startInputAction(context), ) ], ), ), ); } }
总结
两种方案都能解决问题,选哪种取决于你的项目结构偏好。核心逻辑都是确保调用showModalBottomSheet时使用的context是Scaffold组件内部的上下文,这样Flutter才能找到正确的导航栈来渲染模态底部弹窗。
内容的提问来源于stack exchange,提问作者PaavanGupta
相关产品推荐
相关产品推荐

