Flutter - 具有无限高度错误的水平ListView

Flutter - Horizontal ListView with Unbounded height error

当 scrollDirection 设置为垂直时,它按预期工作。问题是当我将 section.axis 设置为 Axis.horizontal 以便 ListView 水平显示小部件时。

使用 Flexible 或 Expanded 小部件无法解决此问题,因为 ListView 的高度需要由列表中的小部件定义。

如您所见,shrinkWrap 也已启用。所以我不知道这里发生了什么,谢谢你的帮助。

控制台说: 'constraints.hasBoundedHeight': 不正确。 导致错误的相关小部件是:ListView

class SectionWidget extends StatelessWidget {
  final Section section;

  const SectionWidget({@required this.section});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(section.title),
        ListView.separated(
          shrinkWrap: true,
          scrollDirection: section.axis,
          physics: section.axis == Axis.vertical
              ? NeverScrollableScrollPhysics()
              : null,
          itemCount: section.itemList.length,
          itemBuilder: (BuildContext context, int index) {
            return Container(
              height: 100,
              width: 100,
              color: Colors.red,
            ); // Just to test if it works
          },
          separatorBuilder: (BuildContext context, int index) {
            double paddingBetween = 10;
            if (section.axis == Axis.horizontal) {
              return SizedBox(width: paddingBetween);
            } else {
              return SizedBox(height: paddingBetween);
            }
          },
        ),
      ],
    );
  }
}

这是因为 Column 或 Row 提供了它们 children 需要的 height/width,而 ListView 从其 parent 中获取了尽可能多的 height/width。

要解决此问题,只需将 ListView 包装在容器中即可。像这样:

import 'package:flutter/material.dart';

class SectionWidget extends StatelessWidget {
  final Section section;

  const SectionWidget({@required this.section});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(section.title),
        Container(
          height: section.axis == Axis.horizontal ? 100 : 700,  // I just set these values
          width: section.axis == Axis.horizontal ? 350 : 100,   // to fit with my device.
          child: ListView.separated(                            // If you want to fit for 
            shrinkWrap: true,                                   // all devices, use MediaQuery
            scrollDirection: section.axis,
            physics: section.axis == Axis.vertical
                ? NeverScrollableScrollPhysics()
                : null,
            itemCount: section.itemList.length,
            itemBuilder: (BuildContext context, int index) {
              return Container(
                height: 100,
                width: 100,
                color: Colors.red,
              ); // Just to test if it works
            },
            separatorBuilder: (BuildContext context, int index) {
              double paddingBetween = 10;
              if (section.axis == Axis.horizontal) {
                return SizedBox(width: paddingBetween);
              } else {
                return SizedBox(height: paddingBetween);
              }
            },
          ),
        ),
      ],
    );
  }
}

有关MediaQuery

的更多信息

编辑:

我认为使用 gridview 会更适合这个。我已经为你重新制作了构建代码以适应不同的 children 大小。 children 的定位和其他我认为你可以管理的东西。

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Expanded(
          child: Text(section.title),
        ),
        SizedBox(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: GridView.builder(
            gridDelegate:
                SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
            shrinkWrap: true,
            scrollDirection: section.axis,
            physics: section.axis == Axis.vertical
                ? NeverScrollableScrollPhysics()
                : null,
            itemCount: section.itemList.length,
            itemBuilder: (context, index) {
              return Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.start,
                children: <Widget>[
                  // Spacer(),
                  Container(
                    margin: EdgeInsets.all(10),
                    height: 100,
                    width: 100,
                    color: Colors.red,
                  ),
                  // Spacer(),
                ],
              );
            },
          ),
        ),
      ],
    );
  }