如何在Flutter中创建GridView布局

60

我试图在Flutter中布局一个4x4的瓷砖网格。我已经用列和行实现了它。但现在我发现了GridView组件。有人可以提供一个使用它实现此功能的例子吗?

我真的无法理解文档。我似乎得不到我想要的结果。

5个回答

120

使用适合您需求的。

  1. GridView.count(...)

    GridView.count(
      crossAxisCount: 2,
      children: <Widget>[
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
      ],
    )
    
  2. GridView.builder(...)

    GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
      itemBuilder: (_, index) => FlutterLogo(),
      itemCount: 4,
    )
    
  3. GridView(...)

    GridView(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
      children: <Widget>[
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
      ],
    )
    
  4. GridView.custom(...)

    GridView.custom(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
      childrenDelegate: SliverChildListDelegate(
        [
          FlutterLogo(),
          FlutterLogo(),
          FlutterLogo(),
          FlutterLogo(),
        ],
      ),
    )
    
  5. GridView.extent(...)

    GridView.extent(
      maxCrossAxisExtent: 400,
      children: <Widget>[
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
        FlutterLogo(),
      ],
    )
    

输出(对于所有内容都相同):

在这里输入图片描述


1
所有解决方案都在一个帖子中,谢谢。它们之间有什么不同? - DolDurma
1
@DolDurma 谢谢,实际上这些小部件之间不应该存在“差异”,它们旨在用于不同的用例,因此请使用最适合您需求的那个。 - CopsOnRoad
数字2是一个很好的选择,谢谢,这篇文章非常有帮助。 - punjabi4life
maxCrossAxisExtent 的意义是什么? - K Pradeep Kumar Reddy
@CopsOnRoad,“GridView.extent”和“GridView.custom”有什么不同? - DolDurma
1
@DolDurma 在 GridView.extent 中,您可以指定 maxCrossAxisExtent,它告诉子元素即使有可用空间也不要超过此宽度。在我的示例中,我使用了 400,这没有太多意义,您可以选择一些较小的值,比如 100,这样就强制子元素保持 <=100 的宽度。 - CopsOnRoad

75

一个简单的例子,将图像加载到瓷砖中。

import 'package:flutter/material.dart';

void main() {
  runApp( MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(

      color: Colors.white30,
      child: GridView.count(
          crossAxisCount: 4,
          childAspectRatio: 1.0,
          padding: const EdgeInsets.all(4.0),
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
          children: <String>[
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
            'http://www.for-example.org/img/main/forexamplelogo.png',
          ].map((String url) {
            return GridTile(
                child: Image.network(url, fit: BoxFit.cover));
          }).toList()),
    );
  }
}

Flutter Gallery应用程序包含一个现实世界的示例,可以在这里找到。

输入图片描述


如果有8个项目,我该如何将网格视图居中显示? - Pratap
请查看以下内容:https://stackoverflow.com/questions/59004532/index-flutter-grid-view - raman raman

42

GridView用于实现Material风格的网格列表。如果您知道您有固定数量的项目并且不是很多(16个可以),则可以使用GridView.count。但是,请注意GridView可滚动,如果这不是您想要的,您最好只使用行和列。

screenshot

import 'dart:collection';
import 'package:flutter/scheduler.dart';
import 'package:flutter/material.dart';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.orange,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Grid Demo'),
      ),
      body: new GridView.count(
        crossAxisCount: 4,
        children: new List<Widget>.generate(16, (index) {
          return new GridTile(
            child: new Card(
              color: Colors.blue.shade200,
              child: new Center(
                child: new Text('tile $index'),
              )
            ),
          );
        }),
      ),
    );
  }
}

如果有8个项目,我该如何将网格视图居中显示? - Pratap

27

请访问这个代码仓库

Widget _gridView() {
    return GridView.count(
      crossAxisCount: 4,
      padding: EdgeInsets.all(4.0),
      childAspectRatio: 8.0 / 9.0,
      children: itemList
          .map(
            (Item) => ItemList(item: Item),
          )
          .toList(),
    );
  }

下面的截图显示了crossAxisCount: 2 这张截图是用于网格数量为2


这个 childAspectRatio: 8.0 / 9.0 是如何计算的?找到 8.0/9.0 的过程是什么? - Ashwin S Ashok
请查看以下链接:https://stackoverflow.com/questions/59004532/index-flutter-grid-view - raman raman
以上链接已失效。 - Yura

17

GridView中有几个针对不同场景的命名构造函数。

构造函数

  1. GridView
  2. GridView.builder
  3. GridView.count
  4. GridView.custom
  5. GridView.extent

以下是GridView构造函数的一个例子:

import 'package:flutter/material.dart';

void main() => runApp(
  MaterialApp(
    home: ExampleGrid(),
  ),
);

class ExampleGrid extends StatelessWidget {
  List<String> images = [
    "https://uae.microless.com/cdn/no_image.jpg",
    "https://images-na.ssl-images-amazon.com/images/I/81aF3Ob-2KL._UX679_.jpg",
    "https://www.boostmobile.com/content/dam/boostmobile/en/products/phones/apple/iphone-7/silver/device-front.png.transform/pdpCarousel/image.jpg",
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgUgs8_kmuhScsx-J01d8fA1mhlCR5-1jyvMYxqCB8h3LCqcgl9Q",
    "https://ae01.alicdn.com/kf/HTB11tA5aiAKL1JjSZFoq6ygCFXaw/Unlocked-Samsung-GALAXY-S2-I9100-Mobile-Phone-Android-Wi-Fi-GPS-8-0MP-camera-Core-4.jpg_640x640.jpg",
    "https://media.ed.edmunds-media.com/gmc/sierra-3500hd/2018/td/2018_gmc_sierra-3500hd_f34_td_411183_1600.jpg",
    "https://hips.hearstapps.com/amv-prod-cad-assets.s3.amazonaws.com/images/16q1/665019/2016-chevrolet-silverado-2500hd-high-country-diesel-test-review-car-and-driver-photo-665520-s-original.jpg",
    "https://www.galeanasvandykedodge.net/assets/stock/ColorMatched_01/White/640/cc_2018DOV170002_01_640/cc_2018DOV170002_01_640_PSC.jpg",
    "https://media.onthemarket.com/properties/6191869/797156548/composite.jpg",
    "https://media.onthemarket.com/properties/6191840/797152761/composite.jpg",
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView(
        physics: BouncingScrollPhysics(), // if you want IOS bouncing effect, otherwise remove this line
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),//change the number as you want
        children: images.map((url) {
          return Card(child: Image.network(url));
        }).toList(),
      ),
    );
  }
}

如果您希望您的GridView项根据内容动态变化,您可以使用几行代码来实现,但最简单的方法是使用StaggeredGridView包。我在这里提供了一个带有示例答案。

下面是GridView.count的示例:

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: ExampleGrid(),
      ),
    );

class ExampleGrid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView.count(
        crossAxisCount: 4,
        children: List.generate(40, (index) {
          return Card(
            child: Image.network("https://robohash.org/$index"),
          ); //robohash.org api provide you different images for any number you are giving
        }),
      ),
    );
  }
}

上面代码片段的屏幕截图:

使用卡片小部件和robohash api的Flutter网格视图示例

SliverGridView的示例:

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: ExampleGrid(),
      ),
    );

class ExampleGrid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        primary: false,
        slivers: <Widget>[
          SliverPadding(
            padding: const EdgeInsets.all(20.0),
            sliver: SliverGrid.count(
              crossAxisSpacing: 10.0,
              crossAxisCount: 2,
              children: List.generate(20, (index) {
                return Card(child: Image.network("https://robohash.org/$index"));
              }),
            ),
          ),
        ],
      )
    );
  }
}

请查看此链接 https://stackoverflow.com/questions/59004532/index-flutter-grid-view - raman raman
感谢,物理学:BouncingScrollPhysics() 对于安卓也是必要的。 - Wilmer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接