AlertDialog内嵌ListView显示空透明窗口并报hasSize断言错误
问题场景
你的AlertDialog使用ListView.builder作为content,搭配自定义deviceList组件后出现布局异常,ListView无法显示,报错信息如下:
The following assertion was thrown during paint():
RenderBox was not laid out: RenderPhysicalShape#aedc0 relayoutBoundary=up2
'package:flutter/src/rendering/box.dart':
Failed assertion: line 2001 pos 12: 'hasSize'
问题原因
核心问题出在deviceList组件的结构设计上:你给外层SizedBox设置了固定高度,但内部Column使用了mainAxisAlignment: MainAxisAlignment.spaceAround,当子组件总高度小于SizedBox的高度时,Column无法完成合理的空间分配计算,导致渲染层出现布局尺寸未确定的断言错误,进而影响外层ListView的正常渲染。
解决方案
提供三种可行的修复方案,可根据你的布局需求选择:
方案一:移除Column的spaceAround属性
如果不需要spaceAround的间距效果,直接移除该属性(默认mainAxisAlignment: MainAxisAlignment.start),通过子组件的margin/padding控制间距:
Widget deviceList(String strDevice) => SizedBox( height: 150.0, child: Column( children: <Widget>[ Row( children: <Widget>[ const Icon(Icons.toys), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(strDevice), ), ], ), const SizedBox(height: 20.0), ], ), );
方案二:给Column添加crossAxisAlignment属性
若要保留spaceAround的布局效果,给Column添加crossAxisAlignment: CrossAxisAlignment.stretch,让Column占满SizedBox的宽度,确保空间计算正常:
Widget deviceList(String strDevice) => SizedBox( height: 150.0, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Row( children: <Widget>[ const Icon(Icons.toys), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(strDevice), ), ], ), const SizedBox(height: 20.0), ], ), );
方案三:移除固定高度的SizedBox
如果不需要固定高度,直接去掉SizedBox,让Column自适应内容高度,同时给ListView.builder添加NeverScrollableScrollPhysics避免嵌套滚动冲突:
// 修改deviceList组件 Widget deviceList(String strDevice) => Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[ Row( children: <Widget>[ const Icon(Icons.toys), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(strDevice), ), ], ), const SizedBox(height: 20.0), ], ); // 修改AlertDialog的ListView配置 return AlertDialog( title: const Text('Choose Device'), content: ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: listDevices.length, itemBuilder: (_, int index) => deviceList(listDevices[index]), ), );
内容的提问来源于stack exchange,提问作者Jaimin Modi

