如何使用GridView在Flutter中创建一个网格列表

在Flutter中开发应用程序时,您可能会遇到需要以网格形式显示项目列表的情况。您可以使用Flutter中的GridView类以网格格式–即有行和列–显示数据。

使用GridView是结合行和列类并创建一个可滚动的网格列表的最佳方式。一个常见的用例是显示一个照片列表,比如在谷歌和苹果的原生照片应用中。

在本教程中,我们将演示如何在你的Flutter应用中实现GridView。我们还将通过一些实际的例子,让你看到GridView的作用。

我们将详细介绍以下内容。

如果你是一个视觉学习者,可以看看这个快速视频教程。

什么是GridView?

在Flutter中,GridView是一个以2D数组形式显示项目列表的部件。简单地说,项目是以表格的形式显示的。

与普通列表不同的是,GridView只在一个方向上显示项目,它同时在水平和垂直方向上显示项目。下图显示了GridView在Flutter应用程序中与普通列表的区别。

GridView in 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 Demo

下面是代码如何被翻译成用户界面的。

Code Translated to UI

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'),
)

复制代码

CrossAxisSpacing

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'),
)

复制代码

MainAxisSpacing

scrollDirection

当GridView以横向模式显示时,你可能想改变滚动方向。将scrollDirection 设置为Axis.horizontal 就可以做到这一点。

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  scrollDirection: Axis.horizontal,
  children: [
    ...
  ],
)

复制代码

GridView Demo Horizontal

physics

这个属性允许你设置列表的滚动行为。你可能根本不希望列表滚动。比方说,你要显示一个图片拼贴。你可以通过将physics 值设置为NeverScrollableScrollPhysics() 来禁用滚动。默认情况下,Android使用ClampingScrollPhysics() ,iOS使用BouncingScrollPhysics() ,看起来像这样。

Physics Comparison

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'))
  ],
)

复制代码

shrinkWrapfalse ,我们需要把GridView包在Expanded widget里面,以便它占用所有可用的空间。否则,它就会出现错误。

显示一个有固定数量的项目的列表

Flutter有一个构造函数,用于在GridView中只显示几个项目,叫做GridView.count() 。这个构造函数使您能够创建一个具有固定数量的项目的GridView。它还简化了指定横轴上项目数量的方法。

示例代码看起来是这样的。

GridView.count(
  crossAxisCount: 3,
  children: [
    ...
  ],
)

复制代码

要在十字轴上显示的项目数被分配给crossAxisCount 属性。如果你仔细观察,你会发现我们不再需要SliverGridDelegateWith FixedCrossAxisCount()

GridView.count() 可以用来创建这样的键盘用户界面。

Keypad UI

下面是上述设计的代码。

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。

让我们试着建立一个这样的产品列表。

Product Listing

代码如下。

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 属性。这可以用来调整项目的高度,如下图所示。

ChildAspectRatio Comparison

构建一个响应式的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包裹在LayoutBuilderLayoutBuilder 提供了constraints ,可以用来确定宽度和高度。利用这些约束条件,我们可以建立各种用户界面。

对于我们的例子,只要屏幕分辨率变为700或更大的宽度,我们就会在横轴上显示四个项目。

下面是输出结果。

GridView Demo Output

结语

如果你已经走到了这一步,你应该掌握了所有必要的技能和基础知识,可以在Flutter中使用GridView创建复杂而有吸引力的网格列表。

这个例子所用的完整代码可以在GitHub上找到。

The postHow to create a grid list in Flutter using GridViewappeared first onLogRocket Blog.

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享