如何让自定义LoadingOverlay覆盖在showModalBottomSheet之上?
解决Flutter中LoadingOverlay被BottomSheet覆盖的层级问题
问题原因
showModalBottomSheet 是添加到Navigator的Overlay层中的,而你的LoadingOverlay嵌套在Scaffold的body内部,层级优先级低于Navigator的Overlay,所以会被BottomSheet盖住。
解决方案:将LoadingOverlay插入到Navigator的Overlay中
通过OverlayEntry可以直接把加载层挂载到Navigator的Overlay里,这样层级会高于BottomSheet,实现全屏遮罩效果。
1. 修改页面组件,维护OverlayEntry
在你的Screen页面中添加OverlayEntry的管理逻辑:
class Screen extends StatefulWidget { @override _ScreenState createState() => _ScreenState(); } class _ScreenState extends State<Screen> { OverlayEntry? _loadingOverlayEntry; // 显示加载遮罩 void showLoading() { if (_loadingOverlayEntry != null) return; // 避免重复添加 _loadingOverlayEntry = OverlayEntry( builder: (context) => CustomLoadingOverlay(), ); Overlay.of(context).insert(_loadingOverlayEntry!); } // 隐藏加载遮罩 void hideLoading() { _loadingOverlayEntry?.remove(); _loadingOverlayEntry = null; } @override void dispose() { hideLoading(); // 页面销毁时确保移除遮罩 super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: _buildScreen(), // 在_buildScreen里调用showLoading/hideLoading和showModalBottomSheet ); } }
2. 确保CustomLoadingOverlay是全屏遮罩
你的自定义加载组件需要铺满整个屏幕,同时屏蔽输入:
class CustomLoadingOverlay extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( onTap: () {}, // 空点击事件屏蔽下层交互 child: Container( width: double.infinity, height: double.infinity, color: Colors.black.withOpacity(0.5), // 半透明背景 child: Center( child: YourCustomSpinner(), // 替换成你的Spinner组件 ), ), ); } }
为什么原来的写法不行?
你之前用Stack把LoadingOverlay放在Scaffold的body内部,这部分属于Scaffold的子组件树,而showModalBottomSheet是挂载在Navigator的Overlay层级中,Flutter的层级优先级是:Navigator Overlay > Scaffold,所以BottomSheet会显示在LoadingOverlay之上。
内容的提问来源于stack exchange,提问作者myd07
相关产品推荐
相关产品推荐

