垂直视口被赋予无限高度

Vertical viewport was given unbounded height

这是我的代码:

@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)

不要使用 Column 进行单子对齐。请改用 Align

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

将网格视图放入 FlexibleExpanded 小部件

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

加上这两行

ListView.builder(
    scrollDirection: Axis.vertical,
    shrinkWrap: true,
...

当您尝试在 Column 中使用 ListView/GridView 时,通常会发生这种情况,有很多解决方法,我在这里列出一些。

  1. ListView 换成 Expanded

    Column(
      children: <Widget>[
        Expanded( // wrap in Expanded
          child: ListView(...),
        ),
      ],
    )
    
  2. ListView包裹在SizedBox中并给出一个有界的height

    Column(
      children: <Widget>[
        SizedBox(
          height: 400, // fixed height
          child: ListView(...),
        ),
      ],
    )
    
  3. ListView中使用shrinkWrap: true

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

有一个名为“中心”的小部件。它应该可以帮助您实现您想做的事情(垂直居中)。 Official Documentation for Center widget

所以,每个人都发布了答案,但没有人关心解释原因: 我将复制有关 shrinkWrap:

的文档

Whether the extent of the scroll view in the [scrollDirection] should be determined by the contents being viewed.

If the scroll view does not shrink wrap, then the scroll view will expand to the maximum allowed size in the [scrollDirection]. If the scroll view has unbounded constraints in the [scrollDirection], then [shrinkWrap] must be true.

Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.

Defaults to false.

所以,根据文档的词汇,这里发生的是我们的 ListView 处于 无限约束(在我们滚动的方向),因此 ListView 会抱怨:

... a vertical viewport was given an unlimited amount of vertical space in which to expand.

通过简单地将 shrinkWrap 设置为 true 将确保它包装由内容定义的大小。一个示例代码来说明:

// ...
  ListView(
    // Says to the `ListView` that it must wrap its
    // height (if it's vertical) and width (if it's horizontal).
    shrinkWrap: true,
  ),
// ...

你的代码就是这样,尽管如此,@Rémi 的建议对于这种情况是最好的,使用 Align 而不是 Column

当一个可滚动小部件嵌套在另一个可滚动小部件中时,通常会发生这种情况。

在我的例子中,我在 Column 中使用了 GridView 并且抛出了该错误。

GridView 小部件有 shrinkWrap property/named 参数,设置它 true 我的问题已解决。

GridView.count(
  shrinkWrap: true,
  // rest of code
)

尽管 shrinkWrap 执行此操作,但您无法在 ListView 中滚动。

如果你想要滚动功能,你可以添加physics 属性:

ListView.builder(
    scrollDirection: Axis.vertical,
    shrinkWrap: true,
    physics: ScrollPhysics(),
...

为第二个列表视图测试这个

ListView.builder(
            physics: NeverScrollableScrollPhysics(),

此答案基于@CopsOnRoad

的北边

发生这种情况是因为 ListView/GridView 小部件没有父级来获取它的大小,所以它的高度是无限的并且 flutter 不知道 ListView 的高度并且无法呈现。

  1. 方案一:固定高度

    直接用ContainerSizedBox包起来写死高度

    Column(
      children: <Widget>[
        SizedBox(
         height: 400, // fixed height
        child: ListView(...),
       ),
     ],
    )
    

这个可以,但是如果高度需要自适应,写了就不行了

  1. 方案二:shrinkWrap: true

    尝试 shrinkWrap: truephysics: ScrollPhysics() 滚动

    shrinkWrap: true有点像android的wrap_content.

    ListView.builder(
       scrollDirection: Axis.vertical,
       shrinkWrap: true,
       physics: ScrollPhysics()
    ...
    

但是编译后,你会发现页面底部有一个长长的黄色警告

所以还是不行

  1. 解决方案三:扩展或灵活

    Flexible是flutter中的灵活布局,相当于android.

    中的LinearLayout

    Flexible中有一个flex属性,等于layout_weight,占了剩下的全部space。

    所以,我们可以用 Flexible 包装 ListView。

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

此答案基于:Vertical viewport was given unbounded height.

    Container(
       height: 100,
       child: ListView.builder(
       scrollDirection: Axis.vertical,
       physics: BouncingScrollPhysics(),
       shrinkWrap: true,
       itemCount: 5,
       itemBuilder: (context, index) {
       return Text("Hello World $index");
      },
    ),
  );

我想 post 另一个答案,因为许多答案(包括已接受的答案!)建议在 ListView.builder 中使用 shrinkWrap: true。虽然这消除了错误,但对于这种情况,此解决方案是 NOT ideal for performance reasons。 Flutter 设计了 ​​ListView 无限大小,专门为了在必要时阻止这种行为!

Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.

在某些 cases/devices 中,此 属性 导致我的项目出现故障滚动和动画滞后。即使延迟不明显,这个 属性 确实会影响滚动性能。

OP 表明他正在为 ListView 创建一个 小(有限)数量的 children。如果我们想解决这些列表的错误,Google recommends 使用 Flexible 小部件,即列表上的 Expanded(具有 flex 1 的 Flexible)本身。

Expanded(
    child: ListView(
        ...
    ),
) 

这里还有其他布局问题,但垂直视口无限高度是因为 ListView 没有限制其大小的 parent。

如果您在 2021 年仍然面临这个问题..这是最好、最简单的解决方案

      ListView.builder(
         scrollDirection: Axis.vertical,
         shrinkWrap: true,
     //     itemExtent: 400, use this if you give hight of your items
        physics: ScrollPhysics(),)

their are many solution .. but they have problem.. like when we use ListView and use its property shrinkWrap .then one thing you many notice the scroll does not work on listView so you must use physics: ScrollPhysics()

解决以上问题的两种方法

1。使用灵活的小部件,

Flexible 小部件可以在行、列中使用,并且 Flex.The 可以灵活扩展以填充主轴中可用的 space(例如,[行的水平方向) ] 或垂直 [Column])

但是,请记住,与 Expanded 不同,Flexible 小部件不需要 child 来填充可用 space。所以,使用 Flexible.

总是更好
Column(
  children: <Widget>[
    Flexible( 
      child: ListView(...),
    ),
  ],
)

2。使用 shrinkWrap:true

使用 shrinkWrap 为真,我们告诉 Listview 将其列表呈现为可用 space,而不是低于剩余屏幕。

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

此外,physics 属性可用于 allow/disallow Listview

的滚动

停止滚动

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

允许滚动

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

 

有很多答案,但每个都有自己的局限性。每个人都在说使用 shrinkWrap: true。是的,你应该使用它,但这些代码的效果是当你滚动列表时,它会自动移动到顶部项目,意味着滚动回到顶部。 所以完美的解决方案是使用 shrinkwrap 和 physics 然后只有列表才能平滑滚动。

      shrinkWrap: true,          //
      physics: ScrollPhysics(),  // both line is mandatory

如果您想查看 Listview.builder 的其他示例,其中列作为子项并且列表可以垂直滚动,那么您可以 see the example here - 在垂直列表中排列多个文本。

只想添加我的解决方案,该解决方案适用于我在同一屏幕上具有垂直列表视图以及其他按钮和文本的情况:

Flexible(
child:  
  ListView.builder(
  // make sure to add the following lines:  
  shrinkWrap: true,
  physics: ScrollPhysics(),
  // the rest of your list view code
 ) // ListView
) // Flexible

此解决方案效果很好,尤其是当您在同一屏幕上有其他小部件时。在这种特殊情况下,单独使用“Expand”或“Flexible”是行不通的。

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

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

Container里面的Column去掉就OK了

在我的例子中,我必须将 ListView 包装在一个容器中并给这个容器一个特定的高度

视口异常原因

GridView / ListView grow until constraints (limits) 停止扩展然后滚动查看超过该尺寸的物品。

Column布局其child任任何约束,完全无视自身尺寸和屏幕尺寸. Column.

里面有无限个space

Viewport was given unbounded height 发生异常是因为 Grid/ListViewColumn.

中扩展到无穷大

Flexible/Expanded 存在给予 Column children 约束 Column's 大小。 (这两个小部件不能在其他任何地方使用,除了 RowColumn 内。)

Column 中的 Flexible/Expanded 小部件内,Grid/ListView 仅使用剩余的 space 未被其他 non-flexible 小部件使用,这些小部件首先布置. (布局阶段信息见底部。)

shrinkWrap 不是一个好的解决方案

Column 中的 ListView 上使用 shrinkWrap: true 并没有太大帮助,因为:

  • ListView 不再滚动
  • ListView还能溢出

A ListView 高度足以显示其所有项目,不会滚动。可以说违背了使用 ScrollView 小部件(parent class of ListView)的目的。

Column布局阶段1(布局阶段的解释见底部),ListView可以是任何它想要的高度(没有限制)。 ListViewshrinkWrap:true 的高度会增加以显示其所有项目。 有了足够的项目,shrinkWrapped ListView 会不断增长(它永远不会滚动)以溢出里面的任何 Column,无论是屏幕还是其他更严格的约束。

不应该 shrinkWrap 只使 ListView 与其项目一样大 剩余 space (达到屏幕高度),然后滚动?

这在直觉上是合理的,但是在第 1 阶段的 Column 布局是在 无界 space[=177 中完成的=].

所以,剩下的 space 是 unlimited/infinite。永远不会达到最大高度。 shrinkWrap:true 随着项目的添加不断增加 Column 高度,直到溢出屏幕(或其他较小的限制)。

示例shrinkWrap:true溢出

下面是一个向 Column 中的收缩包裹 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
              )
            ],
          ),
        ),
      ),
    );
  }
}
对于 Column 中的 GridView/ListView,在 ExpandedFlexible 中换行可能是最安全的解决方案。

扩展/灵活

ExpandedFlexible 只能在 Column 内部使用(以及它的同级 Row 等)。

它们必须作为 Column 的直接 children 使用。我们不能在 SizedBox 或其他小部件中“嵌套”Expanded/Flexible。仅直属Column为直属children.

Column 中,将 ListView/GridView 放在 ExpandedFlexible 中确保它将只使用可用的 space,而不是无限的 space .

Column
→ Expanded
  → ListView

ListView/GridView inside Expanded/Flexible in a Column 不需要 shrinkWrap 因为它受到 Expanded/Flexible 的限制(给定最大高度)小部件。因此,当 constrained/defined 高度用完时,ListView/GridView 将停止增长并开始滚动。


列布局阶段

Column分2阶段布局children:

  • 第一无约束(无界space)
  • 第二,其余 space 基于 Column's parent

阶段 1

Column child notFlexibleExpanded 内的任何 Column 将在第 1 阶段无限布局,无限 space 完全忽略屏幕尺寸.

需要垂直 boundary/constraint 来限制其增长的小部件(例如 ListView)将在阶段 1 中导致 Vertical viewport was given unbounded height 异常,因为 没有垂直边界在无限 space.

大多数小部件都有固有尺寸。例如,Text 仅与其内容和字体一样高 size/style。它不会试图增长来填满 space。 Defined-height 小部件在 Column 布局的第 1 阶段表现良好。

第 2 阶段

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

第 2 阶段根据其 parent 约束计算 Column's 剩余 space 减去 space 在阶段 1 中使用。剩余的 space 作为约束提供给阶段 2 children。

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

.

我做了一个自定义函数来解决你的问题。 您可以在您的代码库中直接使用此函数:

Widget horizontalListView(height, width, color, child, margin) {
return Column(
  children: [
    SizedBox(
      height: 200,
      child: ListView.builder(
        itemCount: 10,
        shrinkWrap: true,
        scrollDirection: Axis.horizontal,
        itemBuilder: (context,index) {
          return Container(
            height: height,
            width: width,
            margin: EdgeInsets.all(margin),
            color: color,
            child: child
          );
        }
      ),
    ),
  ],
 );
})

P.S。抱歉代码对齐不正确。

如果您使用的是 CustomScrollView

你可以试试 SliverFillRemaining