大尺寸(6.7英寸)手机上BottomSheet未显示在屏幕底部问题
问题描述
在对角线为6.7英寸的手机上,showModalBottomSheet 会从屏幕中部开始显示;但在常规尺寸屏幕上,BottomSheet可正常从屏幕底部弹出,且应用内所有BottomSheet组件均出现该异常。
相关代码如下:
void _showRegistrationTrustInfo(BuildContext context) { showModalBottomSheet( isScrollControlled: true, context: context, useSafeArea: true, constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 334 / 668, ), builder: (context) { return BottomSheetBody(children: [ const Expanded(child: RegistrationForTrustInfo()), const SizedBox( height: 20, ), Row( children: [ Expanded( child: ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('Закрыть')), ) ], ) ]); }); }
BottomSheetBody代码:
class BottomSheetBody extends StatelessWidget { const BottomSheetBody({super.key, required this.children}); final List<Widget> children; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 9), child: Column( mainAxisSize: MainAxisSize.max, children: <Widget>[ const TopLine(), const SizedBox( height: 20, ), ...children ], ), ); } }
问题原因
- 固定比例的高度计算不合理:你用
334/668这个基于特定常规屏幕的比例计算maxHeight,6.7英寸手机屏幕高度远大于该基准值,导致计算出的maxHeight接近屏幕高度的50%,直接让BottomSheet显示在屏幕中部。 - Column主轴尺寸设置错误:
BottomSheetBody中的Column使用mainAxisSize: MainAxisSize.max,结合isScrollControlled: true,会强制BottomSheet撑满设置的maxHeight,进一步放大了比例计算的问题。 - Expanded的不当使用:子组件中的
Expanded会强制内容撑满剩余空间,在大屏上加剧了高度溢出的问题。
解决方案
1. 替换固定比例的maxHeight计算
改用通用的相对屏幕高度百分比或固定最大高度,适配不同尺寸屏幕:
constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.7, // 限制为屏幕高度的70% // 或者用固定dp值:maxHeight: 600, ),
2. 调整Column的主轴尺寸
将mainAxisSize改为MainAxisSize.min,让BottomSheet高度由内容自适应,而非强制撑满maxHeight:
class BottomSheetBody extends StatelessWidget { const BottomSheetBody({super.key, required this.children}); final List<Widget> children; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 9), child: Column( mainAxisSize: MainAxisSize.min, // 修改为min children: <Widget>[ const TopLine(), const SizedBox(height: 20), ...children ], ), ); } }
3. 替换Expanded为Flexible(或移除)
如果RegistrationForTrustInfo是可滚动组件,用Flexible替代Expanded,避免强制撑满空间:
// 原代码 const Expanded(child: RegistrationForTrustInfo()), // 修改为 Flexible(child: RegistrationForTrustInfo()),
修改后的完整代码示例
显示BottomSheet的方法
void _showRegistrationTrustInfo(BuildContext context) { showModalBottomSheet( isScrollControlled: true, context: context, useSafeArea: true, constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.7, ), builder: (context) { return BottomSheetBody(children: [ Flexible(child: RegistrationForTrustInfo()), const SizedBox(height: 20), Row( children: [ Expanded( child: ElevatedButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Закрыть'), ), ) ], ) ]); }, ); }
BottomSheetBody组件
class BottomSheetBody extends StatelessWidget { const BottomSheetBody({super.key, required this.children}); final List<Widget> children; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 9), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ const TopLine(), const SizedBox(height: 20), ...children ], ), ); } }
内容的提问来源于stack exchange,提问作者lenol
相关产品推荐
相关产品推荐

