在Flutter中,shrinkWrap属性是用来控制列表是否根据内容来调整自身尺寸的。如果shrinkWrap属性设置为true,列表的尺寸会根据列表项的总高度来调整,因此列表将只占用实际需要的空间。如果shrinkWrap属性设置为false,列表将占用尽可能多的空间,即使列表项的总高度小于列表的高度。默认情况下,shrinkWrap属性的值为false。
在Flutter中,shrinkWrap属性是用来控制列表是否根据内容来调整自身尺寸的。如果shrinkWrap属性设置为true,列表的尺寸会根据列表项的总高度来调整,因此列表将只占用实际需要的空间。如果shrinkWrap属性设置为false,列表将占用尽可能多的空间,即使列表项的总高度小于列表的高度。默认情况下,shrinkWrap属性的值为false。
我刚接触Flutter并非常渴望学习这项技术。我无法理解ListView
中shrinkWrap
属性的作用。我无法理解Flutter文档。
每个ScrollView(ListView,GridView,CustomScrollView)都有一个shrinkWrap属性,用于确定scrollDirection的大小。
ScrollView的scrollDirection可以有两个大小:
1. 与父容器大小相同。
2. 与内容大小(所有子项大小)相同。
如果ScrollView的shrinkWrap属性为false,则ScrollView的scrollDirection大小与父容器大小相同。
如果ScrollView的shrinkWrap属性为true,则ScrollView的scrollDirection大小与内容大小(所有子项大小)相同。
但是,为什么ScrollView的scrollDirection需要在这两个大小之间切换呢?原因是ScrollView的父容器约束条件。
如果ScrollView的父容器给出了紧密或宽松的约束条件,则ScrollView的scrollDirection大小与其父容器大小相同(shrinkWrap为false)。
如果ScrollView的父容器给出了无界约束条件,则ScrollView的scrollDirection大小必须与其内容大小相同(shrinkWrap为true)。否则,它将引发无界高度的运行时异常。
[问题出现的原因]
在Flutter中,ListView是一种常用的列表控件,用于展示大量的数据。默认情况下,ListView的大小会根据其父控件的大小自动调整。然而,有时候我们希望ListView的大小能够根据其子控件的内容来动态调整,以便更好地适应不同的布局需求。这就是引起问题的原因。
[解决方法]
为了解决这个问题,Flutter提供了一个名为shrinkWrap的属性。通过设置shrinkWrap属性,我们可以控制ListView的大小行为。
如果不设置shrinkWrap属性,ListView将会自动扩展到与其父控件一样大。这意味着,如果ListView的父控件是一个Container或者一个Column,ListView将会占据整个可用空间。这在一些情况下可能会导致布局问题。
如果将shrinkWrap属性设置为true,ListView将会根据其子控件的内容来动态调整自己的大小。这意味着,ListView的高度将根据子控件的总高度来计算,并且不会占据额外的空间。这在需要嵌套在其他控件中或者需要根据内容来动态调整大小的情况下非常有用。
下面是一个示例代码,演示了如何使用shrinkWrap属性:
ListView(
shrinkWrap: true,
children:
Text('Item 1'),
Text('Item 2'),
Text('Item 3'),
],
)
在这个示例中,ListView的大小将会根据其子控件的内容来动态调整,而不会占据额外的空间。
通过设置shrinkWrap属性,我们可以更好地控制ListView的大小行为,以适应不同的布局需求。
在Flutter中,ListView(以及GridView、PageView和CustomScrollView)通常会尽量填充父元素提供的所有可用空间,即使列表项所需的空间较少。
通过设置shrinkWrap: true,可以改变这种行为,使ListView只占用所需的空间(当存在更多项时仍可以滚动)。
通过查看以下示例:
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
margin: EdgeInsets.all(32),
decoration: BoxDecoration(border: Border.all(color: Colors.red)),
child: ListView(
shrinkWrap: false,
children:
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
],
),
),
),
),
);
}
}
使用shrinkWrap: false时:
[without shrinkWrap](https://i.stack.imgur.com/dyTBc.png)
使用shrinkWrap: true时:
[with shrinkWrap](https://i.stack.imgur.com/8BYEA.png)
您可以在AlertDialog中使用此属性:当只有少数几个项时,使对话框尽可能小。当有多个项时,填充屏幕高度并使列表可滚动:
[Dialog](https://i.stack.imgur.com/hUE6r.png)
[Dialog](https://i.stack.imgur.com/YIuCe.png)
文档中很好地解释了这一点,“与扩展到最大允许大小相比,收缩包装滚动视图的内容要昂贵得多,因为内容在滚动过程中可以扩展和收缩,这意味着每当滚动位置更改时,滚动视图的大小需要重新计算。”因此,应尽量使用Expanded而不是shrinkWrap,对吗?
非常好的解释,感谢这个。在使用带有shrinkwrap的ListView时,我在iOS上遇到了一个错误。(RenderShrinkWrappingViewport不支持返回内部尺寸)请帮帮我!
关于使用shrinkWrap: true的替代方法的问题,是否有任何适当的解决方法?
以及,[使用slivers](https://dartcodemetrics.dev/docs/rules/flutter/avoid-shrink-wrap-in-lists)可能是一个适当的替代方案。
非常好的解释我写了一个示例:[dartpad.dev/?id=2302f12831923b65e5a47bea07ea3997](https://dartpad.dev/?id=2302f12831923b65e5a47bea07ea3997)
ShrinkWrap vs Slivers | Flutter团队的解释:[youtube.com/watch?v=LUqDNnv_dh0](https://www.youtube.com/watch?v=LUqDNnv_dh0)