You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter问题:ListView.builder设为水平方向却垂直展开

解决Flutter水平ListView垂直方向多余空白问题

你的问题核心在于两个布局错误:

  • 给水平方向的ListView套了Expanded,它会强制ListView占满Column剩余的所有垂直空间,直接导致垂直方向出现大量空白。
  • 水平ListView本身没有垂直高度约束,再加上Expanded的放大作用,空白问题被进一步放大。

修复步骤:

  1. 移除Expanded组件,改用SizedBox固定ListView的垂直高度(和你的颜色块高度保持一致即可,比如32),让ListView仅在垂直方向占用必要空间。
  2. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:25:44