Flutter根据内部widget设置卡片高度 解决GlobalKey获取尺寸返回null问题
问题原因
- 变量名大小写不匹配:代码中定义的GlobalKey名为
_Key(大写K开头),但给Container绑定key时传入的是_key(小写k开头),key实际没有绑定到目标组件上。 - 取值时机错误:GlobalKey关联的组件必须完成首帧布局、挂载到渲染树后,才能通过
currentContext.findRenderObject()拿到尺寸信息。如果在调用showModalBottomSheet后立刻同步读取尺寸,此时组件还未完成渲染,返回结果必然为null。
实现方案
方案1:无需手动获取尺寸,直接自适应内容高度(推荐)
showModalBottomSheet原生支持内容自适应,不需要用GlobalKey手动计算高度,只要保留ListView的shrinkWrap: true配置,不给根容器设置固定高度/满屏高度,弹窗会自动适配内部内容的总高度:
showModalBottomSheet( context: context, useRootNavigator: true, isScrollControlled: true, isDismissible: true, enableDrag: true, builder: (context) { return ListView( shrinkWrap: true, // 让ListView根据子元素总高度调整自身尺寸 padding: EdgeInsets.zero, children: [ PressWidget(), PaddingButtonCard(), // 适配底部安全区 SizedBox(height: MediaQuery.of(context).padding.bottom) ], ); }, );
注意:不要给弹窗根组件设置
height: double.infinity属性,否则弹窗会直接占满全屏,无法触发自适应逻辑。
方案2:需要手动获取组件高度的正确写法
如果业务场景必须拿到组件渲染后的准确尺寸,按以下步骤修改即可:
- 统一GlobalKey的变量名,避免大小写错误
- 通过
addPostFrameCallback监听首帧渲染完成回调,在回调中读取尺寸
// 统一变量命名 final GlobalKey _contentKey = GlobalKey(); showModalBottomSheet( context: context, useRootNavigator: true, isScrollControlled: true, isDismissible: true, enableDrag: true, builder: (context) { // 首帧渲染完成后执行取值逻辑 WidgetsBinding.instance.addPostFrameCallback((_) { final renderBox = _contentKey.currentContext?.findRenderObject() as RenderBox?; if (renderBox != null && renderBox.hasSize) { // 此处可拿到准确的内容高度 final contentHeight = renderBox.size.height; debugPrint("内容高度:$contentHeight"); // 自定义高度调整逻辑写在这里 } }); return Container( key: _contentKey, // 绑定正确的key child: ListView( shrinkWrap: true, padding: EdgeInsets.zero, children: [ PressWidget(), PaddingButtonCard(), ], ), ); }, );
内容的提问来源于stack exchange,提问作者user17838882
相关产品推荐
相关产品推荐

