博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter UI基础 - GridView
阅读量:4050 次
发布时间:2019-05-25

本文共 5550 字,大约阅读时间需要 18 分钟。

GridView

GridView可以构建一个二维网格列表,其默认构造函数定义如下:

GridView({  Axis scrollDirection = Axis.vertical,  bool reverse = false,  ScrollController controller,  bool primary,  ScrollPhysics physics,  bool shrinkWrap = false,  EdgeInsetsGeometry padding,  @required SliverGridDelegate gridDelegate, //控制子widget layout的委托  bool addAutomaticKeepAlives = true,  bool addRepaintBoundaries = true,  double cacheExtent,  List
children = const
[],})

我们可以看到,GridView和ListView的大多数参数都是相同的,它们的含义也都相同的,在此不再赘述。如有疑惑可以翻阅ListView一章。我们唯一需要关注的是gridDelegate参数,类型是SliverGridDelegate,它的作用是控制GridView子组件如何排列(layout)。

gridDelegate:构造 GridView 的委托者,GridView.count 就相当于指定 gridDelegate 为 SliverGridDelegateWithFixedCrossAxisCount,GridView.extent 就相当于指定 gridDelegate 为 SliverGridDelegateWithMaxCrossAxisExtent,它们相当于对普通构造方法的一种封装。它的值是一个 SliverGridDelegate 对象。
SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法。Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent,我们可以直接使用,下面我们分别来介绍一下它们:
 

SliverGridDelegateWithFixedCrossAxisCount

该子类实现了一个横轴为固定数量子元素的layout算法,其构造函数为:

SliverGridDelegateWithFixedCrossAxisCount({  @required double crossAxisCount,   double mainAxisSpacing = 0.0,  double crossAxisSpacing = 0.0,  double childAspectRatio = 1.0,})
  • crossAxisCount:横轴子元素的数量。此属性值确定后子元素在横轴的长度就确定了,即ViewPort横轴长度除以crossAxisCount的商。
  • mainAxisSpacing:主轴方向的间距。
  • crossAxisSpacing:横轴方向子元素的间距。
  • childAspectRatio:子元素在横轴长度和主轴长度的比例。由于crossAxisCount指定后,子元素横轴长度就确定了,然后通过此参数值就可以确定子元素在主轴的长度。
     

可以发现,子元素的大小是通过crossAxisCount和childAspectRatio两个参数共同决定的。注意,这里的子元素指的是子组件的最大显示空间,注意确保子组件的实际大小不要超出子元素的空间。

下面看一个例子:

GridView(  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(      crossAxisCount: 3, //横轴三个子widget      childAspectRatio: 1.0 //宽高比为1时,子widget  ),  children:
[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast) ]);

运行效果如图:

在这里插入图片描述

GridView.count

GridView.count构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount,我们通过它可以快速的创建横轴固定数量子元素的GridView,上面的示例代码等价于:

GridView.count(   crossAxisCount: 3,  childAspectRatio: 1.0,  children: 
[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast), ],);

SliverGridDelegateWithMaxCrossAxisExtent

该子类实现了一个横轴子元素为固定最大长度的layout算法,其构造函数为:

SliverGridDelegateWithMaxCrossAxisExtent({  double maxCrossAxisExtent,  double mainAxisSpacing = 0.0,  double crossAxisSpacing = 0.0,  double childAspectRatio = 1.0,})

maxCrossAxisExtent为子元素在横轴上的最大长度,之所以是“最大”长度,是因为横轴方向每个子元素的长度仍然是等分的。举个例子,如果ViewPort的横轴长度是450,那么当maxCrossAxisExtent的值在区间[450/4,450/3)内的话,子元素最终实际长度都为112.5,而childAspectRatio所指的子元素横轴和主轴的长度比为最终的长度比。其它参数和SliverGridDelegateWithFixedCrossAxisCount相同。

下面我们看一个例子:

 

GridView(  padding: EdgeInsets.zero,  gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(      maxCrossAxisExtent: 120.0,      childAspectRatio: 2.0 //宽高比为2  ),  children: 
[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast), ],);

运行效果如图:

在这里插入图片描述

GridView.extent

GridView.extent构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent,我们通过它可以快速的创建纵轴子元素为固定最大长度的的GridView,上面的示例代码等价于:

GridView.extent(   maxCrossAxisExtent: 120.0,   childAspectRatio: 2.0,   children: 
[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast), ], );

GridView.builder

上面我们介绍的GridView都需要一个widget数组作为其子元素,这些方式都会提前将所有子widget都构建好,所以只适用于子widget数量比较少时,当子widget比较多时,我们可以通过GridView.builder来动态创建子widget。GridView.builder 必须指定的参数有两个:(其中itemBuilder为子widget构建器。)

 

GridView.builder( ... @required SliverGridDelegate gridDelegate,  @required IndexedWidgetBuilder itemBuilder,)

示例:假设我们需要从一个异步数据源(如网络)分批获取一些Icon,然后用GridView来展示:

class InfiniteGridView extends StatefulWidget {  @override  _InfiniteGridViewState createState() => new _InfiniteGridViewState();}class _InfiniteGridViewState extends State
{ List
_icons = []; //保存Icon数据 @override void initState() { // 初始化数据 _retrieveIcons(); } @override Widget build(BuildContext context) { return GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, //每行三列 childAspectRatio: 1.0 //显示区域宽高相等 ), itemCount: _icons.length, itemBuilder: (context, index) { //如果显示到最后一个并且Icon总数小于200时继续获取数据 if (index == _icons.length - 1 && _icons.length < 200) { _retrieveIcons(); } return Icon(_icons[index]); } ); } //模拟异步获取数据 void _retrieveIcons() { Future.delayed(Duration(milliseconds: 200)).then((e) { setState(() { _icons.addAll([ Icons.ac_unit, Icons.airport_shuttle, Icons.all_inclusive, Icons.beach_access, Icons.cake, Icons.free_breakfast ]); }); }); }}
  • _retrieveIcons():在此方法中我们通过Future.delayed来模拟从异步数据源获取数据,每次获取数据需要200毫秒,获取成功后将新数据添加到_icons,然后调用setState重新构建。
  • 在itemBuilder中,如果显示到最后一个时,判断是否需要继续获取数据,然后返回一个Icon。

注意:

Flutter的GridView默认子元素显示空间是相等的,但在实际开发中,你可能会遇到子元素大小不等的情况,如下面这样的布局:

在这里插入图片描述

Pub上有一个包“flutter_staggered_grid_view” ,(一个flutter交错的网格视图,支持多列不同大小的行。)它实现了一个交错GridView的布局模型,可以很轻松的实现这种布局,

 

flutter 禁止GridView滚动:

child: GridView.count(   physics: NeverScrillableScrollPhysics(),)

 

转载地址:http://eonci.baihongyu.com/

你可能感兴趣的文章
Asp.net 默认配置下,Session莫名丢失的原因及解决办法
查看>>
Datawindow.net中如何使用Calendar控件
查看>>
如何在Datawindow.net中实现让当前行选中,并且当前行以其他颜色显示
查看>>
Datawindow.net如何使用导航栏
查看>>
如何利用Datawindow.net提取Sequence数据
查看>>
小诗,纪念我即将到来的结婚两周年
查看>>
自勉文[出处不详,待考证]
查看>>
中国行政级别
查看>>
国家公务员的级别
查看>>
悼念地震死难者:使整个网页变黑白色(灰色)的特效代码
查看>>
asp.net优化完全技巧
查看>>
道 经
查看>>
德 经
查看>>
藏太甲于桐宫-从电视剧康熙王朝中学到的历史知识
查看>>
开发过程中的沟通问题
查看>>
“众”字透出的哲学
查看>>
恋爱爱情婚姻家庭与炒股票
查看>>
答非所问的古今中外名人小笑话幽默
查看>>
周易、命理、风水、姓名与命运交流周易研究心得:姓名学
查看>>
解决asp.net中tabstrip不能点击的问题
查看>>