Flutter问题:ListView.builder设为水平方向却垂直展开
解决Flutter水平ListView垂直方向多余空白问题
你的问题核心在于两个布局错误:
- 给水平方向的ListView套了
Expanded,它会强制ListView占满Column剩余的所有垂直空间,直接导致垂直方向出现大量空白。 - 水平ListView本身没有垂直高度约束,再加上Expanded的放大作用,空白问题被进一步放大。
修复步骤:
- 移除
Expanded组件,改用SizedBox固定ListView的垂直高度(和你的颜色块高度保持一致即可,比如32),让ListView仅在垂直方向占用必要空间。 - 优化item布局:你用Row包裹容器和间距的写法多余,直接给容器加右边距就能实现同样效果,减少不必要的布局层级。
修改后的完整代码:
import 'package:flutter/material.dart'; // widgets import '../widgets/widgets.dart'; class ShopPage extends StatelessWidget { const ShopPage({Key? key}) : super(key: key); // route name static const String routeName = '/shop'; // colors list final List<Color> colors = const [ Color(0xFFEF9A9A), Color(0xFFF48FB1), Color(0xFFCE93D8), Color(0xFFB39DDB), Color(0xFF9FA8DA), Color(0xFF90CAF9), Color(0xFF81D4FA), Color(0xFF80DEEA), Color(0xFF80CBC4), Color(0xFFC5E1A5), Color(0xFFE6EE9C), Color(0xFFFFF59D), Color(0xFFFFE082), Color(0xFFFFCC80), Color(0xFFFFAB91), Color(0xFFF5F5F5), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: const Icon( Icons.arrow_back_ios, size: 20, ), centerTitle: true, title: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.change_history, color: Theme.of(context).colorScheme.secondary, size: 20, ), const SizedBox( width: 10, ), const Text( '20 rects', style: TextStyle( fontSize: 12, fontFamily: 'Inter', fontWeight: FontWeight.bold, ), ), ], ), ), body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.symmetric(horizontal: 38.0), child: Text( 'Companion colors', style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, fontFamily: 'Inter', color: Colors.white, ), ), ), const SizedBox(height: 15), // 替换Expanded为SizedBox固定垂直高度 SizedBox( height: 32, // 和颜色块高度匹配 child: ListView.builder( physics: const BouncingScrollPhysics(), padding: const EdgeInsets.only(left: 38, right: 23), itemBuilder: (context, index) { // 移除多余Row,直接用Padding实现间距 return Padding( padding: const EdgeInsets.only(right: 15), child: Container( height: 32, width: 32, decoration: BoxDecoration( color: colors[index], borderRadius: BorderRadius.circular(32), ), ), ); }, itemCount: colors.length, scrollDirection: Axis.horizontal, ), ), const SizedBox(height: 20), const Padding( padding: EdgeInsets.all(38.0), child: Button( text: 'SELECTED', color: Colors.white, ), ), ], ), ); } }
替代方案:
如果不想固定高度,也可以给ListView设置shrinkWrap: true并移除Expanded,让ListView根据item高度自适应垂直空间,但要确保item的高度是确定的,避免布局异常:
ListView.builder( shrinkWrap: true, // 其他参数保持不变 )
内容的提问来源于stack exchange,提问作者dipansh
相关产品推荐
相关产品推荐

