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

如何在Row中实现宽度自适应内容的垂直ListView

解决方案

要实现左侧ListView自适应内容宽度、右侧内容占满剩余空间的Row布局,可以通过自定义Scrollable组件结合Viewport来解决,核心是修改Viewport的crossAxisFit参数为CrossAxisFit.loose,让其宽度由子项内容决定而非填满父级约束。

完整代码示例:

home: Scaffold(
  body: Row(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      // 自定义可滚动列表,实现宽度自适应内容
      Scrollable(
        axisDirection: AxisDirection.down,
        // 保持列表可滚动的物理特性
        physics: const AlwaysScrollableScrollPhysics(),
        viewportBuilder: (BuildContext context, ViewportOffset offset) {
          return Viewport(
            offset: offset,
            // 关键设置:宽度由子项最大宽度决定
            crossAxisFit: CrossAxisFit.loose,
            slivers: [
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) => Text('item $index'),
                  // 可根据实际需求调整条目数量
                  childCount: 100,
                ),
              ),
            ],
          );
        },
      ),
      Expanded(
        child: Container(
          color: Colors.green,
          child: const Text('Some text here'),
        ),
      ),
    ],
  ),
),

原理说明

  • 默认的ListView内部使用的Viewport会设置crossAxisFit: CrossAxisFit.fill,强制占满父级提供的横向空间,这就是它无法自适应内容宽度的原因。
  • 通过自定义Scrollable+Viewport,将crossAxisFit改为CrossAxisFit.loose,Viewport会自动计算子项的最大宽度并以此作为自身宽度,实现自适应效果。
  • 保留AlwaysScrollableScrollPhysics确保列表在条目过多时仍可正常滚动,兼顾性能(懒加载特性和原生ListView一致)。

为什么之前的尝试有问题

  • ConstrainedBox:固定最大宽度无法适配动态内容,不符合需求。
  • Flexible+Expanded(flex:5):依赖屏幕宽度分配比例,而非内容本身的宽度。
  • IntrinsicWidth+ListView:ListView内部的RenderViewport/RenderShrinkWrappingViewport不支持返回固有尺寸,因此会抛出错误。
  • SingleChildScrollView+Column:条目过多时会一次性构建所有子项,性能较差,不适合大量数据场景。

内容的提问来源于stack exchange,提问作者Alexander Marochko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:30:35