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

如何在Column中使用ListView.Builder且无需shrinkWrap与硬编码高度?

问题描述

我尝试在与SliverAppBar同级的Column中嵌入ListView.builder,因此需要借助CustomScrollView和SliverToBoxAdapter让Column能在CustomScrollView中运行。开启shrinkWrap=true时功能正常,但官方文档指出该设置性能开销大,会抵消ListView.Builder的懒加载优势。当前报错为“RenderFlex children have non-zero flex but incoming height constraints are unbounded”,原因是Column高度无限。由于是响应式适配脚手架,我不想硬编码Column尺寸,请问如何实现无需shrinkWrap和硬编码高度的布局?

解决方案

核心问题是CustomScrollView + SliverToBoxAdapter 组合下,内部的Column无法获取明确的高度约束,导致嵌套的ListView.builder没有固定高度参考。以下两种方案可解决问题:

方案一:用LayoutBuilder动态获取约束

利用LayoutBuilder拿到父容器的可用高度,给ListView设置最大高度,既不需要硬编码,也能保留懒加载特性:

import 'package:flutter/material.dart';

class TestScaffold extends StatelessWidget {
  const TestScaffold({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey[100],
      body: CustomScrollView(
        slivers: [
          // 可在此添加你的SliverAppBar
          // SliverAppBar(title: Text('Demo'), pinned: true),
          SliverToBoxAdapter(
            child: LayoutBuilder(
              builder: (context, constraints) {
                // 计算ListView可用高度:父容器总高度减去标题的预估高度(也可通过MediaQuery精准获取)
                final listViewHeight = constraints.maxHeight - 40;
                return Row(
                  children: [
                    Expanded(
                      child: Column(
                        children: [
                          const Text('Title 1'),
                          ConstrainedBox(
                            constraints: BoxConstraints(maxHeight: listViewHeight),
                            child: ListView.builder(
                              itemCount: 3,
                              itemBuilder: (context, index) {
                                return Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Container(
                                    height: 100,
                                    width: 100,
                                    color: Colors.red,
                                  ),
                                );
                              },
                            ),
                          ),
                        ],
                      ),
                    ),
                    const SizedBox(width: 10),
                    Expanded(
                      child: Column(
                        children: [
                          const Text('Title 2'),
                          ConstrainedBox(
                            constraints: BoxConstraints(maxHeight: listViewHeight),
                            child: ListView.builder(
                              itemCount: 3,
                              itemBuilder: (context, index) {
                                return Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Container(
                                    height: 100,
                                    width: 100,
                                    color: Colors.green,
                                  ),
                                );
                              },
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

方案二:拆分结构用Sliver组件组合

既然使用了CustomScrollView,直接将页面拆分为多个Sliver组件,避免嵌套Column+ListView的约束冲突,更符合CustomScrollView的设计逻辑:

import 'package:flutter/material.dart';

class TestScaffold extends StatelessWidget {
  const TestScaffold({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey[100],
      body: CustomScrollView(
        slivers: [
          // 你的SliverAppBar
          // SliverAppBar(title: Text('Demo'), pinned: true),
          // 顶部标题行
          SliverToBoxAdapter(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: const [
                Expanded(child: Center(child: Text('Title 1'))),
                SizedBox(width: 10),
                Expanded(child: Center(child: Text('Title 2'))),
              ],
            ),
          ),
          // 双列列表区域
          SliverToBoxAdapter(
            child: SizedBox(
              // 计算高度:屏幕总高度减去状态栏、AppBar和标题行的高度
              height: MediaQuery.of(context).size.height - kToolbarHeight - 40,
              child: Row(
                children: [
                  Expanded(
                    child: ListView.builder(
                      itemCount: 3,
                      itemBuilder: (context, index) {
                        return Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Container(
                            height: 100,
                            width: 100,
                            color: Colors.red,
                          ),
                        );
                      },
                    ),
                  ),
                  const SizedBox(width: 10),
                  Expanded(
                    child: ListView.builder(
                      itemCount: 3,
                      itemBuilder: (context, index) {
                        return Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Container(
                            height: 100,
                            width: 100,
                            color: Colors.green,
                          ),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

关键说明

  • 方案一保留原有嵌套结构,通过动态获取高度实现适配,适合需要维持原有布局层级的场景;
  • 方案二更贴合CustomScrollView的设计思路,拆分组件后避免了嵌套约束冲突;
  • 两种方案都不需要设置shrinkWrap=true,完全保留ListView.builder的懒加载性能优势,同时满足响应式适配需求。

内容的提问来源于stack exchange,提问作者Martin Palmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 20:45:02