Flutter - 水平 ListView 出现无限高度错误

3

当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);
            }
          },
        ),
      ],
    );
  }
}
1个回答

2
那是因为Column或Row会给它们的子组件提供所需的高度/宽度,而ListView会利用其父组件中可用的尽可能多的高度/宽度。
要解决这个问题,只需将ListView包装在一个Container中。像这样:
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的更多信息,请参考。

编辑:

我认为使用网格视图会更适合这种情况。我已经重新制作了构建代码,以适应不同孩子的尺寸。我认为您可以处理孩子的位置和其他一些事情。

  @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(),
                ],
              );
            },
          ),
        ),
      ],
    );
  }

1
这对我发布的代码确实有效,但如果我想让子项具有动态高度/宽度怎么办?基本上我希望ListView能够根据其子项的尺寸进行调整,有什么选项吗? - Valen G.
列表视图会根据其子项的尺寸进行调整。每个红色框都在垂直和水平模式下具有100的宽度和高度。您能否向我提供一些描述问题的图片? - rkdupr0n
1
你说得对,在我发布的代码中,子元素的宽度和高度都是100,但在我的实际应用程序中,我不知道子元素的大小,因此在这种情况下,用容器包装ListView并固定尺寸不是一个好选择。 - Valen G.
我认为这是不可能的,所以我打算让所有的子元素大小都相同。 - Valen G.
我已经编辑了我的答案。看看吧!我认为它可以适用于不同大小的小部件,但请告诉我。干杯! - rkdupr0n
@ValenG。请查看此链接,它为您提供了解决方案!https://dev59.com/FMPra4cB1Zd3GeqPkaL3 - sm_sayedi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接