【问题标题】:How to create GridView Layout in FlutterFlutter - 布局网格
【发布时间】:2017-10-26 07:09:22
【问题描述】:

我正在尝试在颤动中布局一个 4x4 的瓷砖网格。我设法用列和行来做到这一点。但现在我找到了GridView 组件。谁能提供一个如何使用它的例子?

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

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    GridView 用于实现材料grid lists。如果您知道您有固定数量的项目并且不是很多(16 个很好),您可以使用GridView.count。但是,您应该注意 GridView 是可滚动的,如果这不是您想要的,最好只使用行和列。

    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 个项目,我如何在中心显示网格视图
    【解决方案2】:

    将图像加载到图块中的简单示例。

    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 应用包含一个真实世界的示例,可以在 here 找到。

    【讨论】:

    【解决方案3】:

    请访问此repo

    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

    【讨论】:

    【解决方案4】:

    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 包。我已通过示例here 提供了答案。

    以下是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
            }),
          ),
        );
      }
    }
    

    上面sn-p的截图:

    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"));
                  }),
                ),
              ),
            ],
          )
        );
      }
    }
    

    【讨论】:

    【解决方案5】:

    使用适合您需要的任何一个。

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

    输出(所有人都一样):

    【讨论】:

    • 一篇文章中的所有解决方案,谢谢。他们之间有什么不同?
    • @DolDurma 谢谢,这些小部件之间不应该有任何“差异”之类的东西,它们旨在用于不同的用例,所以请使用更适合您需要的那个。
    • 2 号是个不错的选择,感谢这篇文章很有帮助
    • maxCrossAxisExtent 有什么意义?
    • @DolDurma 在GridView.extent 中,您指定maxCrossAxisExtent,它告诉孩子即使有可用空间也不要超过这个宽度。在我的示例中,我使用了 400,这没有多大意义,请选择一些较小的值,例如 100,而您正在强迫孩子们单独保持 &lt;=100 宽度。