前言

GridView可以构建一个二维网格列表。需要关注的是gridDelegate参数,类型是SliverGridDelegate,它的作用是控制GridView子组件如何排列(layout)。SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法。Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent。

接口描述

GridView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required this.gridDelegate,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
}) const SliverGridDelegateWithFixedCrossAxisCount({
@required this.crossAxisCount,
// 主轴方向的间距
this.mainAxisSpacing = 0.0,
// 横轴方向子元素的间距
this.crossAxisSpacing = 0.0,
// 子元素在横轴长度和主轴长度的比例
this.childAspectRatio = 1.0,
}) const SliverGridDelegateWithMaxCrossAxisExtent({
// 为子元素在横轴上的最大长度,之所以是“最大”长度,是因为横轴方向每个子元素的长度仍然是等分的
@required this.maxCrossAxisExtent,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
// 所指的子元素横轴和主轴的长度比为最终的长度比
this.childAspectRatio = 1.0,
})

代码示例

// GridView

// GridView可以构建一个二维网格列表。需要关注的是gridDelegate参数,类型是SliverGridDelegate,它的作用是控制GridView子组件如何排列(layout)。
// SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法。
// Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent。 // SliverGridDelegateWithFixedCrossAxisCount
import 'package:flutter/material.dart'; class GridViewTest1 extends StatelessWidget{
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('SliverGridDelegateWithFixedCrossAxisCount'),
),
body: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 横轴三个子widget
crossAxisCount: 3,
// 宽高比为1时,子widget
childAspectRatio: 1.0
),
children: <Widget>[
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast)
],
), // 等价于 // body: GridView.count(
// crossAxisCount: 3,
// childAspectRatio: 1.0,
// children: <Widget>[
// Icon(Icons.ac_unit),
// Icon(Icons.airport_shuttle),
// Icon(Icons.all_inclusive),
// Icon(Icons.beach_access),
// Icon(Icons.cake),
// Icon(Icons.free_breakfast),
// ],
// ) );
}
} // SliverGridDelegateWithMaxCrossAxisExtent
class GridViewTest2 extends StatelessWidget{
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('SliverGridDelegateWithMaxCrossAxisExtent'),
),
body: GridView(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 元素在横轴上的最大长度
maxCrossAxisExtent: 120.0,
// 元素在横轴和主轴的长度比为最终的长度比
childAspectRatio: 2.0,
),
children: <Widget>[
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast)
],
), // 等价于 // body: GridView.extent(
// maxCrossAxisExtent: 120.0,
// childAspectRatio: 2.0,
// children: <Widget>[
// 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
// 从一个异步数据源(如网络)分批获取一些Icon
class InfiniteGridView extends StatefulWidget{
@override
_InfiniteGridViewState createState() => _InfiniteGridViewState();
} class _InfiniteGridViewState extends State<InfiniteGridView>{
// 保存Icon数据
List<IconData> _icons = []; @override
void initState(){
// 初始化数据
_retrieveIcons();
} @override
Widget build(BuildContext context){ return Scaffold(
appBar: AppBar(
title: Text(''),
),
body: 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.free_breakfast,
]);
});
});
} }

总结

在实际开发中,可能会遇到子元素大小不等的情况,Pub上有一个包“flutter_staggered_grid_view” ,它实现了一个交错GridView的布局模型,可以很轻松的实现这种布局。

【Flutter】可滚动组件之GridView的更多相关文章

  1. 【Flutter学习】可滚动组件之ScrollView

    一,概述 ScrollView 是一个带有滚动的视图组件. 二,组成部分 ScrollView 由三部分组成: Scrollable - 它监听各种用户手势并实现滚动的交互设计.可滚动Widget都直 ...

  2. 【Flutter】可滚动组件之CustomScrollView

    前言 CustomScrollView是可以使用Sliver来自定义滚动模型(效果)的组件.它可以包含多种滚动模型,举个例子,假设有一个页面,顶部需要一个GridView,底部需要一个ListView ...

  3. 【Flutter】可滚动组件简介

    前言 当组件内容超过当前显示视口(ViewPort)时,如果没有特殊处理,Flutter则会提示Overflow错误.为此,Flutter提供了多种可滚动组件(Scrollable Widget)用于 ...

  4. 【Flutter】可滚动组件之滚动控制和监听

    前言 可以用ScrollController来控制可滚动组件的滚动位置. 接口描述 ScrollController({ // 初始滚动位置 double initialScrollOffset = ...

  5. 【Flutter】可滚动组件之ListView

    前言 它可以沿一个方向线性排布所有子组件,并且它也可以支持基于Sliver的延迟构建模型. 接口描述 ListView({ Key key, // 可滚动widget公共参数 Axis scrollD ...

  6. 【Flutter】可滚动组件之SingleChildScrollView

    前言 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件. 接口描述 const SingleChildScrollView({ Key ke ...

  7. 第30讲 UI组件之 GridView组件

    第30讲 UI组件之 GridView组件 1.网格布局组件GridView GridView是一个ViewGroup(布局控件),可使用表格的方式显示组件,可滚动的控件.一般用于显示多张图片,比如实 ...

  8. Flutter中用ListView嵌套GridView报错异常

    flutter中的ListView组件和GridView组件都是常用的布局组件,有时候ListView中需要嵌套GridView来使用,例如下图: 这种情况就需要在ListView里面再嵌套一个Gri ...

  9. flutter系列之:flutter中常用的GridView layout详解

    目录 简介 GridView详解 GridView的构造函数 GridView的使用 总结 简介 GridView是一个网格化的布局,如果在填充的过程中子组件超出了展示的范围的时候,那么GridVie ...

随机推荐

  1. Apriori 算法-如何进行关联规则挖掘

    公号:码农充电站pro 主页:https://codeshellme.github.io 在数据分析领域有一个经典的故事,叫做"尿布与啤酒". 据说,在美国西部的一家连锁超市发现, ...

  2. 题解 CF1062E Company

    \(\texttt{Solution}\) 数据结构学傻的蒟蒻来写一个新思路 这题的正解是利用多个结点的 \(lca\) 是 \(dfs\) 序最大的结点和 \(dfs\) 序最小的结点的 \(lca ...

  3. Python条件判断和循环语句

    一.条件判断语句 通过一条或多条语句的判断来决定是否执行代码块 1.if语句基本形式: if 判断条件:    语句块 例如: score=75if score>=60:    print &q ...

  4. 可选链plugin-proposal-optional-chaining的使用(优化)

    第一步 安装 npm install --save-dev @babel/plugin-proposal-optional-chaining 然后在.babelrc.js文件夹里进行配置 plugin ...

  5. 三方登录微博url接口

    1.创建apps/oauth模块进行oauth认证 '''2.1 在apps文件夹下新建应用: oauth''' cd syl/apps python ../manage.py startapp oa ...

  6. 双向数据绑定 v-model

    双向数据绑定 就是既可以从页面传到数据也可以从数据到页面 初始运行结果为: 在输入框 更改数据 相应的输入框上的也会相对改变 然后再试试利用控制台更改数据 可以看到数据也被改变了 而且输入框中的内容也 ...

  7. global和nonlocal之间的区别

    在局部修全局的:global 在局部修改嵌套的:nonlocal nonlocal代码示范 # 在局部作用域内去修改嵌套作用域内的变量# 当我们在局部作用域内要修改嵌套作用域内的变量时,需要使用non ...

  8. 初识SylixOs

    SylixOS 概述 SylixOS 是一款大型嵌入式实时操作系统,诞生于 2006 年,起初它只是一个小型多任务调度器,经过多年开发,SylixOS 目前已经成为一个功能完善.性能卓越.可靠稳定的嵌 ...

  9. burpsuite 2020.12.1最新版蓝色版,下载安装破解

    最新版Burpsuite下载破解安装 安装包链接:https://cloud.189.cn/t/qUVzYbuAJzqm(访问码:mw12) 1.首先,我们解压,可以看到解压后的文件夹里有如下文件 2 ...

  10. Erlang那些事儿第2回之我是模块(module),一文件一模块

    前几篇文章会写得比较基础,但是既然要写一系列的文章,还是得从基础开始写.我刚学Erlang碰到最大的问题是,想网上搜索下语法,结果却是寥寥无几,而且介绍得不是很系统,对我了解一些细节是有影响的,正好我 ...