没有显式高度的水平 ListView 抖动

Horizontal ListView flutter WITHOUT explicit height

我正在尝试创建没有预设高度的水平滚动listview.builder()

我试过将 shrinkwrap 设置为 true 并将其包装在 Expanded/Flexible.

目前达到预期效果的唯一方法(我发现)是在一列内的 singlechildscrollview 内换行,按照这个答案 (Flutter: Minimum height on horizontal list view)。

该方法的问题是没有构建器方法将动态数据加载到 singlechildscrollview 内的卡片中。

我的问题是如何创建一个水平 listview,它通过嵌套在 singlechildscrollview (Flutter: Minimum height on horizontal list view) 中的 row 生成输出,但带有生成器方法?

灵活

Scaffold(
  body: Container(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Flexible(
          child: ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: 3,
            itemBuilder: (BuildContext context, int index) {
              return FeaturedCard();
            },
          ),
        ),
        Flexible(
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: 10,
            itemBuilder: (BuildContext context, int index) {
              return FeaturedCard();
            },
          ),
        ),
      ],
    ),
  ),
)

结果: https://i.stack.imgur.com/XKiWo.jpg

singlechildscrollview 中嵌套了 row(有效的方法)

 Container(
  padding: EdgeInsets.only(top: 16, bottom: 8),
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: <Widget>[
            FeaturedCard(),
            FeaturedCard(),
          ],
        ),
      ),
    ],
  ),
)

结果: https://i.stack.imgur.com/va3TY.jpg

注意使用 flexible 时卡内添加的 space(这实际上在不同的设备上呈现更差)

Flutter 框架只能在构建后知道小部件的高度。

如果您正在动态构建 ListView 个子项,它无法计算 ListView 所需的高度,直到它的所有子项都已构建,这可能永远不会发生(无限 ListView).

您可以给 ListView 一个固定的高度并动态构建它的子项,或者让 ListView's 高度取决于它的子项,在这种情况下您需要预先构建它的所有子项.

为将答案编辑到问题中的 OP 发布答案

通过像这样创建自定义生成器方法解决了问题:

Widget _buildFeaturedCards(List<Product> product) {
  final cards = <Widget>[];
  Widget FeautredCards;

  if (product.length > 0) {
    for (int i = 0; i < product.length; i++) {
      cards.add(FeaturedCard(product[i]));
      print(product.length);
    }
    FeautredCards = Container(
      padding: EdgeInsets.only(top: 16, bottom: 8),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(children: cards),
          ),
        ],
      ),
    );
  } else {
    FeautredCards = Container();
  }
  return FeautredCards;
}

这会预先创建必要的滚动小部件,而不是像 ListView.builder 那样懒惰地创建。