简体   繁体   English

如何在 Flutter 中创建 GridView 布局

[英]How to create GridView Layout in Flutter

I am trying to layout a 4x4 grid of tiles in flutter.我正在尝试在颤动中布局一个 4x4 的瓷砖网格。 I managed to do it with columns and rows.我设法用列和行来做到这一点。 But now I found the GridView component.但现在我找到了GridView组件。 Could anyone provide an example on how to do it using it?任何人都可以提供一个如何使用它的例子吗?

I can't really wrap my head around the docs.我无法真正理解文档。 I don't seem to get the results I want.我似乎没有得到我想要的结果。

Use whichever suits your need.使用适合您需要的任何一种。

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

Output (same for all):输出(全部相同):

在此处输入图片说明

A simple example loading images into the tiles.将图像加载到图块中的简单示例。

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

The Flutter Gallery app contains a real world example, which can be found here . Flutter Gallery 应用程序包含一个真实世界的示例,可在此处找到。

在此处输入图片说明

GridView is used for implementing material grid lists . GridView用于实现材质网格列表 If you know you have a fixed number of items and it's not very many (16 is fine), you can use GridView.count .如果您知道您有固定数量的项目并且不是很多(16 个就可以),您可以使用GridView.count However, you should note that a GridView is scrollable, and if that isn't what you want, you may be better off with just rows and columns.但是,您应该注意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'),
              )
            ),
          );
        }),
      ),
    );
  }
}

Please visit this repo .请访问这个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(),
    );
  }

Below screenshot contains crossAxisCount: 2下面的屏幕截图包含crossAxisCount: 2 此屏幕截图用于网格计数 2

There are few named constructors in GridView for different scenarios, GridView针对不同场景的命名构造函数很少,

Constructors构造函数

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

Below is a example of GridView constructor:下面是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(),
      ),
    );
  }
}

If you want your GridView items to be dynamic according to the content, you can few lines to do that but the simplest way to use StaggeredGridView package.如果你希望你的 GridView 项目根据内容是动态的,你可以用几行来做到这一点,但最简单的方法是使用StaggeredGridView包。 I have provided an answer with example here .在这里提供了一个例子的答案。

Below is an example for a GridView.count :以下是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
        }),
      ),
    );
  }
}

Screenshot for above snippet:上述代码段的屏幕截图:

blasanka 使用卡片小部件和 robohash api 的 Flutter gridview 示例

Example for a SliverGridView : 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"));
              }),
            ),
          ),
        ],
      )
    );
  }
}

You can use a flutter_layout_grid package您可以使用flutter_layout_grid

First of all, we need to add it to our pubspec.yaml :首先,我们需要将它添加到our pubspec.yaml

dependencies:
  flutter_layout_grid: ^1.0.3

Then, we can define a custom ItemCardLayoutGrid widget to show each ItemCard inside a LayoutGrid widget:然后,我们可以定义一个自定义ItemCardLayoutGrid小部件以在LayoutGrid小部件中显示每个ItemCard

import 'package:flutter_layout_grid/flutter_layout_grid.dart';

class ItemCardLayoutGrid extends StatelessWidget {
  const ItemCardLayoutGrid({
    Key? key,
    required this.crossAxisCount,
    required this.items,
  })  
  // we only plan to use this with 1 or 2 columns
  : assert(crossAxisCount == 1 || crossAxisCount == 2),
    // assume we pass an list of 4 items for simplicity
    assert(items.length == 4),
    super(key: key);
  final int crossAxisCount;
  final List<ItemCardData> items;

  @override
  Widget build(BuildContext context) {
    return LayoutGrid(
      // set some flexible track sizes based on the crossAxisCount
      columnSizes: crossAxisCount == 2 ? [1.fr, 1.fr] : [1.fr],
      // set all the row sizes to auto (self-sizing height)
      rowSizes: crossAxisCount == 2
          ? const [auto, auto]
          : const [auto, auto, auto, auto],
      rowGap: 40, // equivalent to mainAxisSpacing
      columnGap: 24, // equivalent to crossAxisSpacing
      // note: there's no childAspectRatio
      children: [
        // render all the cards with *automatic child placement*
        for (var i = 0; i < items.length; i++)
          ItemCard(data: items[i]),
      ],
    );
  }
}

And pass a list of children inside a loop (our ItemCard widgets):并在循环中传递一个子项列表(我们的ItemCard小部件):

children: [
  // render all the cards with *automatic child placement*
  for (var i = 0; i < items.length; i++)
    ItemCard(data: items[i]),
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM