这是我的代码:

@override
Widget build(BuildContext context) {
  return new Material(
    color: Colors.deepPurpleAccent,
    child: new Column(
     mainAxisAlignment: MainAxisAlignment.center,
        children:<Widget>[new GridView.count(crossAxisCount: _column,children: new List.generate(_row*_column, (index) {
          return new Center(
              child: new CellWidget()
          );
        }),)]
    )
  );
}

例外情况如下:

I/flutter ( 9925): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 9925): The following assertion was thrown during performResize():
I/flutter ( 9925): Vertical viewport was given unbounded height.
I/flutter ( 9925): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 9925): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 9925): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 9925): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 9925): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 9925): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 9925): the height of the viewport to the sum of the heights of its children.
I/flutter ( 9925): 
I/flutter ( 9925): When the exception was thrown, this was the stack:
I/flutter ( 9925): #0      RenderViewport.performResize.<anonymous closure> (package:flutter/src/rendering/viewport.dart:827:15)
I/flutter ( 9925): #1      RenderViewport.performResize (package:flutter/src/rendering/viewport.dart:880:6)
I/flutter ( 9925): #2      RenderObject.layout (package:flutter/src/rendering/object.dart:1555:9)

当前回答

也会遇到这种错误,因为代码是这样的

return Container(
      child: Column(
        children: [
          ListView.separated(
              itemBuilder: (context, index) {
                return CircleManagerSettingItem(widget.membersInfo[index]);
              },
              separatorBuilder: (_, index) => DD(
                    height: 1,
                    paddingLeft: 10,
                    paddingRight: 10,
                  ),
              itemCount: (widget.membersInfo.length)),
        ],
      ),
    );

删除容器内的列,然后确定。

其他回答

不要使用Column进行单子对齐。使用Align代替。

new Align(
  alignment: Alignment.topCenter,
  child: new GridView(),
)

这通常发生在你试图在一个列中使用一个ListView/GridView时,有很多方法来解决它,我在这里列出了几个。

将ListView包装为Expanded 列( 孩子们:<部件> ( Expanded(// wrap in Expanded . 孩子:列表视图(…), ), ), ) 在sizebox中包装ListView并给出一个有界的高度 列( 孩子们:<部件> ( SizedBox ( 高度:400,//固定高度 孩子:列表视图(…), ), ), ) 在ListView中使用shrinkWrap: true。 列( 孩子们:<部件> ( 列表视图( shrinkWrap: true, //使用这个 ), ), )

ListView.builder(
                scrollDirection: Axis.vertical,
                shrinkWrap: true,
                itemCount: 10,
                itemBuilder: (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Container(
                      height: 100,
                      width: double.infinity,
                      color: Colors.pinkAccent,

                    ),
                  );
                },
              ),

Viewport异常的原因

GridView / ListView增长,直到约束(限制)停止这种扩展,然后滚动查看超出该大小的项目。

但是Column没有任何约束地布局它的子节点,完全忽略了它自己的大小和屏幕大小。柱内空间无限。

由于Grid/ListView在列内扩展到无穷大,导致Viewport被给予无界高度异常。

灵活/扩展的存在给列的子约束基于列的大小。(除了在Row和Column中,这两个小部件不能在其他任何地方使用。)

在Column中的Flexible/Expanded小部件中,Grid/ListView只使用未被其他非Flexible小部件占用的剩余空间,这些小部件首先被布局。(布局阶段信息见底部。)

shrinkWrap不是一个好的解决方案

在列的ListView中使用shrinkWrap: true并没有真正的帮助,因为:

ListView不再滚动 ListView仍然会溢出

一个足够高的ListView来显示它所有的项,不会滚动。可以说,这违背了使用ScrollView小部件(ListView的父类)的目的。

在列布局阶段1(见底部布局阶段的解释),ListView可以是任何它想要的高度(没有限制)。 带有shrinkWrap:true的ListView将增加高度以显示其所有项。 有了足够多的项目,一个收缩包装的ListView将增长&增长(它从不滚动)溢出任何列在里面,无论是屏幕或其他更严格的约束。

难道shrinkWrap不应该只是让ListView只和它的项目或剩余空间一样大(直到屏幕高度),然后滚动吗?

这在直觉上是有意义的,但是在第一阶段的Column布局中是在无界空间中完成的。

所以剩余空间是无限的。没有达到最大高度。true只会随着项目的增加而不断增加列的高度,直到满屏(或其他较小的约束)。

使用实例shrinkWrap:true溢出

下面是一个例子,将项目添加到一个列的收缩包装的ListView中,直到它的高度高于屏幕,创建一个溢出警告区域:

(只要一直按+号浮动动作按钮)

import 'package:flutter/material.dart';

class ColumnListViewPage extends StatefulWidget {
  @override
  _ColumnListViewPageState createState() => _ColumnListViewPageState();
}

class _ColumnListViewPageState extends State<ColumnListViewPage> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Column & ListView'),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            _count++;
          });
        },
      ),
      body: SafeArea(
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(color: Colors.red)
          ),
          /// // without center, Column will be as narrow as possible
          alignment: Alignment.center,
          /// Column is forced (constrained) to match screen dimension,
          child: Column(
            children: [
              Text('Inner (Nested) Column'),
              ListView.separated( // ← should be wrapped in Expanded
                itemCount: _count,
                separatorBuilder: (context, index) => const Divider(),
                itemBuilder: (context, index) => Padding(
                  padding: const EdgeInsets.symmetric(vertical: 38.0),
                  child: Text('Row $index'),
                ),
                shrinkWrap: true, // should be removed
              )
            ],
          ),
        ),
      ),
    );
  }
}

对于列中的GridView/ListView,在Expanded或Flexible中包装可能是最安全的解决方案。


扩展/灵活

Expanded和Flexible只能在Column(以及它的兄弟姐妹Row等)中使用。

它们必须作为Column的直接子节点使用。我们不能在SizedBox或其他小部件中“嵌套”Expanded/Flexible。仅直接在列下作为直系子女。

在Column中,将ListView/GridView放置在Expanded或Flexible中可以确保它只使用可用空间,而不是无限空间。

Column
→ Expanded
  → ListView

列中的Expanded/Flexible中的ListView/GridView不需要shrinkWrap,因为它是受限的(给定一个max。通过Expanded/Flexible小部件。因此,当约束/定义高度用完时,ListView/GridView将停止增长并开始滚动。


栏目布局阶段

列将子元素分为两个阶段:

第一无约束(无界空间) 第二,剩余空间基于列的父节点

第一阶段

任何不在Flexible或Expanded中的Column子元素都将在阶段1中被布局,在无限的空间中,完全忽略屏幕大小。

需要垂直边界/约束来限制其增长的小部件(例如ListView)将在阶段1中导致vertical viewport被给予无界高度异常,因为在无界空间中没有垂直边界。

大多数小部件都有固有大小。以文本为例,它的高度取决于它的内容和字体大小/样式。它不会为了填满空间而生长。定义高度的小部件在列布局的第一阶段表现良好。

第二阶段

任何增长到填充边界的小部件,都应该放在阶段2的Flexible或Expanded布局中。

阶段2计算Column的父约束减去阶段1中使用的空间的剩余空间。剩余的空间作为约束提供给阶段2的子节点。

例如,ListView只会增长到使用剩余空间并停止,避免视口异常。

更多关于列布局算法和如何扩展工作在它。

我们可以用两种方法来解决上述问题

1. 使用灵活的部件,

Flexible小部件可以在Row、Column和Flex中使用。扩展以填充主轴中的可用空间的灵活性(例如,水平扩展[Row]或垂直扩展[Column])

但是,请记住,与Expanded不同,The Flexible小部件不需要子部件填充可用空间。所以,最好使用Flexible。

Column(
  children: <Widget>[
    Flexible( 
      child: ListView(...),
    ),
  ],
)

2. 使用shrinkWrap: true

使用shrinkWrap为true,我们告诉Listview渲染它的List到可用空间,而不是在剩余屏幕以下。

Column(
  children: <Widget>[
    ListView(
      shrinkWrap: true, 
    ),
  ],
)

此外,物理属性可以用来允许/禁止滚动Listview

停止滚动

 ListView(
      shrinkWrap: true, 
      physics: NeverScrollableScrollPhysics(),
    ),

允许滚动

 ListView(
      shrinkWrap: true, 
      physics: ScrollPhysics(),
    ),