Flutter如何将ListTile组件高度设置为0
ListView 中 ListTile 高度无法匹配子组件问题
问题场景
构建使用ListTile的ListView组件时,将值为false的元素对应容器高度设置为1,但这些元素仍然占据大量多余空白。需要实现ListTile高度匹配内部子组件,或直接跳过值为false的元素。
原有实现代码
List<bool> isRed2 = [ true,true,false,false, true,true,true,false, false,false,true,true, false,true,true,true, true,]; return ListView.builder( padding: EdgeInsets.all(0), scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: isRed2.length, itemBuilder: (context, i) => ListTile( dense: true, minVerticalPadding: 0, contentPadding: EdgeInsets.all(0), minLeadingWidth: 0, horizontalTitleGap: 0, title: isRed2[i] ? Container( height: 50, color: Colors.red, ) : Container( height: 1, color: Colors.blue, )));
运行效果

约束条件
- 无法在
ListTile外层包裹Container或SizedBox组件,长列表渲染时会出现性能下降问题 - 必须使用
ListTile保证渲染速度,不使用ListTile直接自定义组件会降低加载性能 - 提前筛选值为
true的元素生成新列表再构建的方案不符合当前业务场景需求
解决方案
方案1:零开销跳过false项
不需要提前过滤原列表,直接在itemBuilder逻辑中判断,值为false时返回const SizedBox.shrink()即可。该组件是常量构造的零尺寸组件,渲染开销可忽略,不会造成长列表性能损耗,完全符合约束要求。
修改后的itemBuilder代码:
itemBuilder: (context, i) { if (!isRed2[i]) { return const SizedBox.shrink(); } return ListTile( dense: true, minVerticalPadding: 0, contentPadding: EdgeInsets.all(0), minLeadingWidth: 0, horizontalTitleGap: 0, title: Container( height: 50, color: Colors.red, ) ); }
方案2:解除ListTile默认高度约束(需保留false项场景使用)
多余空白的本质是ListTile遵循Material设计规范自带强制最小高度,即使设置dense: true、minVerticalPadding: 0也会保留默认最小高度。不需要在外层包裹尺寸组件,直接给ListTile添加两个属性即可让高度完全跟随子组件:
- 添加
visualDensity: const VisualDensity(vertical: -4),将垂直方向视觉密度调到最低,压缩默认内边距 - Flutter 3.10及以上版本可额外添加
minTileHeight: 0,直接将ListTile最小高度强制设为0
适配后的false项ListTile代码:
ListTile( dense: true, minVerticalPadding: 0, contentPadding: EdgeInsets.all(0), minLeadingWidth: 0, horizontalTitleGap: 0, visualDensity: const VisualDensity(vertical: -4), minTileHeight: 0, // 仅Flutter 3.10+版本支持 title: Container( height: 1, color: Colors.blue, ) )
两种方案均满足所有约束条件:未在ListTile外层包裹尺寸组件、保留ListTile原生高性能渲染逻辑、无需提前筛选修改原列表数据。
内容的提问来源于stack exchange,提问作者范植勝
相关产品推荐
相关产品推荐

