Flutter中如何在不设固定高度的情况下用ListView展示卡片?
解决水平ListView.builder的"unbounded height"错误
问题原因
当水平滚动的ListView.builder被放在Column组件中时,Column的垂直方向不会给子元素提供明确的尺寸约束。而水平ListView本身在垂直方向没有固有高度,Flutter无法确定它的高度,因此抛出"unbounded height"错误。SingleChildScrollView+Row能正常运行,是因为Row的高度由子元素(TestCard)的高度决定,SingleChildScrollView会直接继承这个高度。
解决方案
给水平的ListView.builder指定垂直方向的明确高度,常用两种实现方式:
方式1:用SizedBox固定高度
直接给ListView.builder包裹一个SizedBox,设置height为卡片的实际高度(比如TestCard的高度为180,就对应设置height:180):
Widget ListViaListView(Size screenSize){ return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "Card List With ListView.builder", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontFamily: 'Montserrat', fontSize: 16 ), ), addVerticalSpace(12), // 包裹SizedBox指定垂直高度 SizedBox( height: 180, // 替换为TestCard的实际高度 child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: 2, itemBuilder: (context, index) { return const TestCard(); }, ), ) ], ); }
方式2:用Expanded占满Column剩余空间
如果希望水平列表占满Column中标题下方的所有垂直空间,可以用Expanded包裹ListView.builder:
Widget ListViaListView(Size screenSize){ return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "Card List With ListView.builder", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontFamily: 'Montserrat', fontSize: 16 ), ), addVerticalSpace(12), // 用Expanded分配剩余垂直空间 Expanded( child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: 2, itemBuilder: (context, index) { return const TestCard(); }, ), ) ], ); }
额外说明
- 无需设置
shrinkWrap: true:该属性主要用于垂直ListView在不确定高度时收缩到内容高度,这里我们已经明确了垂直高度,设置该属性反而会增加不必要的布局计算。 - 若TestCard高度动态,可尝试用
IntrinsicHeight包裹,但该组件会遍历子元素计算高度,性能损耗较大,不推荐在长列表中使用。
内容的提问来源于stack exchange,提问作者Emre Turan
相关产品推荐
相关产品推荐

