垂直视口被赋予无限高度

pal*_*ara 36 flutter flutter-layout

我是新来的人.只需将我的网格视图居中:

在此输入图像描述

以下是我试过的代码:

  @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()
            );
          }),)]
      )
    );
  }
Run Code Online (Sandbox Code Playgroud)

例外情况如下:

    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)
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Blo*_*oss 60

加这两行

ListView.builder(
    scrollDirection: Axis.vertical,
    shrinkWrap: true,
...
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,只是一个小建议,你可以用Flexible包围ListView以使其可滚动 (19认同)
  • 这是“shrinkWrap”的文档 https://api.flutter.dev/flutter/widgets/ScrollView/shrinkWrap.html (4认同)
  • 为了供将来参考,请注意,根据文档,如果列表视图中有很多小部件,将“shrinkWrap”设置为 true 的成本可能会更高。请参阅文档中的这段代码:“收缩包裹滚动视图的内容比扩展到允许的最大大小要昂贵得多,因为内容在滚动过程中可以扩展和收缩,这意味着需要重新计算滚动视图的大小”每当滚动位置改变时。` (4认同)
  • `shrinkWrap: true` 很昂贵,它使我的列表变得滞后,这个问题通过用 Flex 包围我的 ListView 来解决。 (2认同)

Gui*_*lla 44

因此,每个人都发布了答案,但没有人愿意解释原因:我将复制有关以下内容的文档shrinkWrap

[scrollDirection]中滚动视图的范围是否应由正在查看的内容决定。

如果滚动视图不收缩环绕,则滚动视图将扩展到 [scrollDirection] 中允许的最大大小。如果滚动视图在 [scrollDirection] 中有无限约束,则 [shrinkWrap] 必须为 true。

收缩包装滚动视图的内容比扩展到允许的最大大小要昂贵得多,因为内容可以在滚动过程中扩展和收缩,这意味着每当滚动位置发生变化时都需要重新计算滚动视图的大小。

默认为false.

因此,使用文档的词汇,这里发生的事情是我们ListView处于无限约束的情况(在我们滚动的方向上),因此ListView会抱怨:

...垂直视口被赋予无限量的垂直空间来扩展。

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

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

这就是与你的代码去,尽管如此,@雷米的建议是最好的这种情况下,使用Align代替Column


Bak*_*ker 37

视口异常的原因

\n

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

\n

Column对其子元素的布局没有任何限制,完全忽略了其自身的大小和屏幕大小。里面有无限的空间Column

\n

Viewport was given unbounded height发生异常是因为Grid/ListView在 a 内扩展到无穷大Column.

\n

Flexible/Expanded存在是为了给Column孩子们基于Column\'s尺寸的约束。(这两个小部件不能在其他任何地方使用,除了 insideRowColumn。)

\n

在 的Flexible/Expanded小部件内ColumnGrid/ListView仅使用未被其他非灵活小部件占用的剩余空间,这些小部件首先布局。(有关布局阶段信息,请参阅底部。)

\n

shrinkWrap不是一个好的解决方案

\n

在 a 内部使用shrinkWrap: trueonListViewColumn并没有多大帮助,因为:

\n
    \n
  • ListView不再滚动
  • \n
  • ListView仍然可以溢出
  • \n
\n

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

\n

Column布局阶段 1 中(有关布局阶段的说明,请参阅底部),ListView可以是所需的任何高度(没有限制)。\nA将增加高度以显示其所有项目。\n有了足够的项目,aListView将不断增长(它永远不会滚动)溢出任何东西shrinkWrap:trueshrinkWrapped ListViewColumn内部的任何内容,无论是屏幕还是其他更严格的约束。

\n
不应该shrinkWrap只制作ListView与其物品一样大的尺寸或者,然后滚动吗?
\n

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

\n

因此,剩余空间是无限的/无限的。永远不会达到最大高度。shrinkWrap:true只是不断增长Column项目的添加,高度不断增加,直到溢出屏幕(或其他较小的限制)。

\n

例子shrinkWrap:true溢出

\n

下面是一个示例,将项目添加到收缩包裹的ListViewa 中Column,直到其高度高于屏幕,从而创建溢出警告区域:

\n

(只需按住+号浮动操作按钮)

\n
import \'package:flutter/material.dart\';\n\nclass ColumnListViewPage extends StatefulWidget {\n  @override\n  _ColumnListViewPageState createState() => _ColumnListViewPageState();\n}\n\nclass _ColumnListViewPageState extends State<ColumnListViewPage> {\n  int _count = 0;\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\'Column & ListView\'),\n      ),\n      floatingActionButton: FloatingActionButton(\n        child: Icon(Icons.add),\n        onPressed: () {\n          setState(() {\n            _count++;\n          });\n        },\n      ),\n      body: SafeArea(\n        child: Container(\n          decoration: BoxDecoration(\n            border: Border.all(color: Colors.red)\n          ),\n          /// // without center, Column will be as narrow as possible\n          alignment: Alignment.center,\n          /// Column is forced (constrained) to match screen dimension,\n          child: Column(\n            children: [\n              Text(\'Inner (Nested) Column\'),\n              ListView.separated( // \xe2\x86\x90 should be wrapped in Expanded\n                itemCount: _count,\n                separatorBuilder: (context, index) => const Divider(),\n                itemBuilder: (context, index) => Padding(\n                  padding: const EdgeInsets.symmetric(vertical: 38.0),\n                  child: Text(\'Row $index\'),\n                ),\n                shrinkWrap: true, // should be removed\n              )\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
对于GridView/ListViewa 来说Column,包裹在Expandedor内Flexible可能是最安全的解决方案。
\n
\n

扩展/灵活

\n

Expanded并且Flexible只能在内部使用Column(及其兄弟姐妹如Row等)。

\n

它们必须用作 的直接子代Column。我们不能“嵌套” Expanded/FlexibleSizedBox其他小部件。仅直接Column作为直系子级。

\n

在内部Column,放置ListView/GridViewExpanded确保Flexible它将仅使用可用空间,而不是无限空间。

\n
Column\n\xe2\x86\x92 Expanded\n  \xe2\x86\x92 ListView\n
Run Code Online (Sandbox Code Playgroud)\n

ListView/GridViewExpanded/Flexiblea内部Column不需要,shrinkWrap因为它受到小部件的约束(给定最大高度)Expanded/Flexible。因此,当约束/定义的高度用完时,ListView/GridView将停止增长并开始滚动。

\n
\n

列布局阶段

\n

Column将孩子分为两个阶段:

\n
    \n
  • 第一无限制(无限空间)
  • \n
  • 第二个,剩余空间基于Column\'s父级
  • \n
\n

阶段1

\n

任何不在里面的Column孩子都会在第一阶段被放置在无限、无限的空间中,完全忽略屏幕尺寸FlexibleExpanded

\n

需要垂直边界/约束来限制其增长的小部件(例如)将在第一阶段ListView引起异常,因为无界空间中没有垂直边界Vertical viewport was given unbounded height

\n

大多数小部件都有固有的大小。 Text例如,仅与其内容和字体大小/样式一样高。它不会试图通过生长来填充空间。定义高度的小部件在Column布局的第一阶段表现良好。

\n

阶段2

\n

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

\n

第 2 阶段Column\'s根据其父约束减去第 1 阶段中使用的空间来计算剩余空间。该剩余空间作为约束提供给第 2 阶段的子级。

\n

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

\n

Column有关布局算法及其Expanded内部工作原理的更多信息

\n


Cop*_*oad 29

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

  1. ListView起来Expanded

    Column(
      children: <Widget>[
        Expanded( // wrap in Expanded
          child: ListView(...),
        ),
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)
  2. ListViewSizedBox并给予有限height

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

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use this
        ),
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

  • 尝试使用包含水平列表视图的垂直列表视图。只有sizedbox方法可以工作,但它对高度的规定过于严格。还有什么办法可以做到这一点? (7认同)
  • `shrinkWrap: true` 完成了这项工作 (2认同)
  • 这是最好的答案。请注意,如果“ListView”内部有很多元素并且“shrinkWrap”设置为“true”,则其成本明显更高。摘自文档:“收缩包装滚动视图的内容比扩展到允许的最大大小要昂贵得多,因为内容在滚动过程中可以扩展和收缩,这意味着每当滚动视图的大小需要重新计算滚动位置发生变化。"` (2认同)

Man*_*mar 15

将网格视图放在Flexible或Expanded小部件中

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(),
          );
        }),))]
    )
);
Run Code Online (Sandbox Code Playgroud)

  • 展开并向 GridView 添加 `shrinkWrap: true`。 (2认同)

Rob*_*bin 15

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

在我的情况下,我在 Column 内使用 GridView 并且该错误抛出。

GridView 小部件具有shrinkWrap属性/命名参数,设置它true我的问题是固定的。

GridView.count(
  shrinkWrap: true,
  // rest of code
)
Run Code Online (Sandbox Code Playgroud)


Ali*_*esh 14

虽然shrinkWrap做这件事,但你不能滚动ListView

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

ListView.builder(
    scrollDirection: Axis.vertical,
    shrinkWrap: true,
    physics: ScrollPhysics(),
...
Run Code Online (Sandbox Code Playgroud)


Par*_*iya 12

这个答案基于@CopsOnRoad 的北部

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

  1. 解决方案一:固定高度

    直接用Container或包裹起来SizedBox写死高度。

    Column(
      children: <Widget>[
        SizedBox(
         height: 400, // fixed height
        child: ListView(...),
       ),
     ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

这很好,但是如果高度需要自适应,那么你写它就行不通了。

  1. 解决方案二:shrinkWrap: true

    试着shrinkWrap: truephysics: ScrollPhysics()滚动

    shrinkWrap: true有点像 android 的wrap_content.

    ListView.builder(
       scrollDirection: Axis.vertical,
       shrinkWrap: true,
       physics: ScrollPhysics()
    ...
    
    Run Code Online (Sandbox Code Playgroud)

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

所以还是不能

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

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

    有一个 Flexibleflex属性,等于 layout_weight ,占用所有剩余空间。

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

    Column(
      children: <Widget>[
        Expanded( 
          child: ListView(...),
        ),
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

这个答案基于:垂直视口被赋予无限的高度。


Kam*_*kar 10

答案有很多种,但每个答案都有其局限性。每个人都在说使用 shrinkWrap: true。是的,您应该使用它,但这些代码的效果是当您滚动列表时,它将自动移动到顶部项目,意味着滚动回顶部。所以完美的解决方案是使用物理收缩包裹,这样只有列表才能平滑滚动。

      shrinkWrap: true,          //
      physics: ScrollPhysics(),  // both line is mandatory
Run Code Online (Sandbox Code Playgroud)

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


小智 8

添加这两行

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

...


Pra*_*tti 6

我想发布另一个答案,因为许多答案(包括已接受的答案!)建议使用shrinkWrap: truein ListView.builder。虽然这消除了错误,但由于这种情况下的性能原因,该解决方案并不理想。Flutter 设计ListView为无限大小,专门为了仅在必要时阻止这种行为!

收缩包装滚动视图的内容比扩展至允许的最大大小要昂贵得多,因为内容在滚动过程中可能会扩展和收缩,这意味着每当滚动位置发生变化时,都需要重新计算滚动视图的大小。

在某些情况/设备中,此属性会导致我的项目出现滚动故障和动画滞后。即使延迟不明显,此属性也会影响滚动性能。

OP 显示他正在为创造少量(有限)的孩子ListView。如果我们想解决这些列表的错误,Google建议在列表本身上使用Flexible小部件,即Expanded(带有 flex 1 的)。Flexible

Expanded(
    child: ListView(
        ...
    ),
) 
Run Code Online (Sandbox Code Playgroud)

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


Rém*_*let 5

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

    new Align(
      alignment: Alignment.topCenter,
      child: new GridView(),
    )
Run Code Online (Sandbox Code Playgroud)