在Flutter中开发应用程序时,您可能会遇到需要以网格形式显示项目列表的情况。您可以使用Flutter中的GridView类以网格格式–即有行和列–显示数据。
使用GridView是结合行和列类并创建一个可滚动的网格列表的最佳方式。一个常见的用例是显示一个照片列表,比如在谷歌和苹果的原生照片应用中。
在本教程中,我们将演示如何在你的Flutter应用中实现GridView。我们还将通过一些实际的例子,让你看到GridView的作用。
我们将详细介绍以下内容。
如果你是一个视觉学习者,可以看看这个快速视频教程。
什么是GridView?
在Flutter中,GridView是一个以2D数组形式显示项目列表的部件。简单地说,项目是以表格的形式显示的。
与普通列表不同的是,GridView只在一个方向上显示项目,它同时在水平和垂直方向上显示项目。下图显示了GridView在Flutter应用程序中与普通列表的区别。
下面是让GridView启动和运行的最小代码。
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
children: [
Image.network('https://picsum.photos/250?image=1'),
Image.network('https://picsum.photos/250?image=2'),
Image.network('https://picsum.photos/250?image=3'),
Image.network('https://picsum.photos/250?image=4'),
],
)
复制代码
gridDelegate
是一个控制列表中项目显示方式的属性。在我们的例子中,它被赋予了SliverGridDelegateWithFixedCrossAxisCount()
,crossAxisCount
设置为3
。这意味着如果滚动方向是垂直的,我们要水平显示三个项目,如果滚动方向是水平的,则垂直显示三个项目。任何列表的默认滚动方向都只是垂直的,所以这些项目是水平显示的。
children
指的是这里给出的项目列表。它接受任何部件的列表,所以你可以显示任何你想出现在屏幕上的东西。
这里是输出结果。
下面是代码如何被翻译成用户界面的。
GridView属性
让我们看一下GridView的一些属性。
crossAxisSpacing
为这个属性设置一个值可以让你在横轴上的项目之间放置一个空间。这意味着如果滚动方向是垂直的,空间将在水平方向上出现。
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16),
children: [
Image.network('https://picsum.photos/250?image=1'),
Image.network('https://picsum.photos/250?image=2'),
Image.network('https://picsum.photos/250?image=3'),
)
复制代码
mainAxisSpacing
主轴指的是列表滚动的轴。滚动方向上的项目之间的空间是用mainAxisSpacing
属性给出的。
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 16),
children: [
Image.network('https://picsum.photos/250?image=1'),
Image.network('https://picsum.photos/250?image=2'),
Image.network('https://picsum.photos/250?image=3'),
)
复制代码
scrollDirection
当GridView以横向模式显示时,你可能想改变滚动方向。将scrollDirection
设置为Axis.horizontal
就可以做到这一点。
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
scrollDirection: Axis.horizontal,
children: [
...
],
)
复制代码
physics
这个属性允许你设置列表的滚动行为。你可能根本不希望列表滚动。比方说,你要显示一个图片拼贴。你可以通过将physics
值设置为NeverScrollableScrollPhysics()
来禁用滚动。默认情况下,Android使用ClampingScrollPhysics()
,iOS使用BouncingScrollPhysics()
,看起来像这样。
shrinkWrap
将shrinkWrap
值设置为true
,使GridView在滚动方向上只占用所需的空间来填充项目。这默认为false
,即使项目不在列表中,也会保留整个屏幕。
/////shrinkWrap: false,
Column(
children: [
Expanded(
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
shrinkWrap: false,
children: [... ],
),
),
ElevatedButton(onPressed: () {}, child: Text('Close'))
],
)
/////shrinkWrap: true,
Column(
children: [
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
shrinkWrap: true,
children: [...],
),
ElevatedButton(onPressed: () {}, child: Text('Close'))
],
)
复制代码
当shrinkWrap
是false
,我们需要把GridView包在Expanded widget里面,以便它占用所有可用的空间。否则,它就会出现错误。
显示一个有固定数量的项目的列表
Flutter有一个构造函数,用于在GridView中只显示几个项目,叫做GridView.count()
。这个构造函数使您能够创建一个具有固定数量的项目的GridView。它还简化了指定横轴上项目数量的方法。
示例代码看起来是这样的。
GridView.count(
crossAxisCount: 3,
children: [
...
],
)
复制代码
要在十字轴上显示的项目数被分配给crossAxisCount
属性。如果你仔细观察,你会发现我们不再需要SliverGridDelegateWith FixedCrossAxisCount()
。
GridView.count()
可以用来创建这样的键盘用户界面。
下面是上述设计的代码。
GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
padding: EdgeInsets.only(left: 24, right: 24),
children: [
DialKey(
number: '1',
letters: '',
),
...
],
)
复制代码
shrinkWrap
属性被设置为true
,这使得GridView在屏幕上腾出一些空间。
DialKey()
是一个自定义的widget,用来显示一个单键。它看起来像这样。
// DialKey widget
class DialKey extends StatelessWidget {
final String number;
final String letters;
DialKey({this.number, this.letters});
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 80,
height: 80,
child: FloatingActionButton(
onPressed: () {},
backgroundColor: Colors.grey.withOpacity(0.5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$number',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
Text(
'$letters',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)
],
),
),
),
);
}
}
复制代码
在GridView中显示一个长列表
要显示一个长的列表或无限多的可能来自数据库的项目,你需要GridView.builder()
构造函数。
下面是示例代码。
GridView.builder(
itemCount: 100,
itemBuilder: (context, index) => ItemTile(index),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
)
复制代码
itemCount
代表项目的数量。这有助于GridView估计最大滚动范围。
itemBuilder
根据当前的索引创建给定的widget。
让我们试着建立一个这样的产品列表。
代码如下。
GridView.builder(
itemCount: 100,
itemBuilder: (context, index) => ItemTile(index),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 2,
),
)
class ItemTile extends StatelessWidget {
final int itemNo;
const ItemTile(
this.itemNo,
);
@override
Widget build(BuildContext context) {
final Color color = Colors.primaries[itemNo % Colors.primaries.length];
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
tileColor: color.withOpacity(0.3),
onTap: () {},
leading: Container(
width: 50,
height: 30,
color: color.withOpacity(0.5),
child: Placeholder(
color: color,
),
),
title: Text(
'Product $itemNo',
key: Key('text_$itemNo'),
),
),
);
}
}
复制代码
在上面的代码中,需要注意的一件事是childAspectRatio
属性。这可以用来调整项目的高度,如下图所示。
构建一个响应式的GridView
随着Flutter 2.0的发布,现在除了移动端,您还可以为网页和桌面开发应用程序。在构建跨平台的应用程序时,您要确保通过创建尽可能好的用户体验来迎合网络用户。在这种情况下,当网格在大屏幕上显示时,在网格上显示更多的项目可以大大改善网络用户的用户体验。
让我们修改前面的代码,在大屏幕上显示时,在横轴上显示更多的项目。
//Before
GridView.builder(
itemCount: 100,
itemBuilder: (context, index) => ItemTile(index),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 2,
),
)
//After
LayoutBuilder(builder: (context, constraints) {
return GridView.builder(
itemCount: 100,
itemBuilder: (context, index) => ItemTile(index),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 1,
childAspectRatio: 5,
),
);
})
复制代码
将GridView包裹在LayoutBuilder
。LayoutBuilder
提供了constraints
,可以用来确定宽度和高度。利用这些约束条件,我们可以建立各种用户界面。
对于我们的例子,只要屏幕分辨率变为700或更大的宽度,我们就会在横轴上显示四个项目。
下面是输出结果。
结语
如果你已经走到了这一步,你应该掌握了所有必要的技能和基础知识,可以在Flutter中使用GridView创建复杂而有吸引力的网格列表。
这个例子所用的完整代码可以在GitHub上找到。
The postHow to create a grid list in Flutter using GridViewappeared first onLogRocket Blog.