flutter3.0学习笔记

GridView

Preview
  • GridView.count
  • GridView.extent
  • GridView.builder

网格布局是一种常见的布局类型,GridView 组件正是实现了网格布局的组件。 主要通过Count、extent、custom、builder构造列表。有内边距、是否反向、滑动控制器等属性。 四个属性使用场景,Count、extent、custom适用于子布局较少时使用。可能会用到上拉刷新,数据较多时,则使用builder属性。其构造:

GridView({
    super.key,
    super.scrollDirection,//滚动方向
    super.reverse,
    super.controller,
    super.primary,
    super.physics,
    super.shrinkWrap,
    super.padding,
    required this.gridDelegate,//控制GridView子组件如何排列(layout)
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    super.cacheExtent,
    List<Widget> children = const <Widget>[],
    int? semanticChildCount,
    super.dragStartBehavior,
    super.clipBehavior,
    super.keyboardDismissBehavior,
    super.restorationId,
  }) 

SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法。Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCountSliverGridDelegateWithMaxCrossAxisExtent

  • SliverGridDelegateWithFixedCrossAxisCount 该子类实现了一个横轴为固定数量子元素的layout算法,其构造函数为:
const SliverGridDelegateWithFixedCrossAxisCount({
    required this.crossAxisCount,//横轴子元素的数量
    this.mainAxisSpacing = 0.0,//主轴方向的间距
    this.crossAxisSpacing = 0.0,//横轴方向子元素的间距
    this.childAspectRatio = 1.0,//子元素在横轴长度和主轴长度的比例
    this.mainAxisExtent,
  })

例子:

import 'package:flutter/material.dart';

class GridViewPage extends StatefulWidget {
  const GridViewPage({Key? key}) : super(key: key);
  @override
  State<GridViewPage> createState() => _GridViewPageState();
}

class _GridViewPageState extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView网格组件'),),
      body: GridView(
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,//横轴3个
          childAspectRatio: 1.0,//宽高比1
        ),
        children: const [
          Icon(Icons.ac_unit),
          Icon(Icons.apple),
          Icon(Icons.android),
          Icon(Icons.access_time_filled),
          Icon(Icons.share_location),
          Icon(Icons.star_half),
        ],
      ),
    );
  }
}

image.png

  • SliverGridDelegateWithMaxCrossAxisExtent 该子类实现了一个横轴子元素为固定最大长度的layout算法,其构造:
 const SliverGridDelegateWithMaxCrossAxisExtent({
    required this.maxCrossAxisExtent,//子元素在横轴上的最大长度,横轴方向每个子元素的长度仍然是等分的
    this.mainAxisSpacing = 0.0,
    this.crossAxisSpacing = 0.0,
    this.childAspectRatio = 1.0,
    this.mainAxisExtent,
  }) 

例子:

import 'package:flutter/material.dart';

class GridViewPage extends StatefulWidget {
  const GridViewPage({Key? key}) : super(key: key);
  @override
  State<GridViewPage> createState() => _GridViewPageState();
}

class _GridViewPageState extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView网格组件'),),
      body: GridView(
        gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 120,
          childAspectRatio: 2,//宽高比2
        ),
        children: const [
          Icon(Icons.ac_unit),
          Icon(Icons.apple),
          Icon(Icons.android),
          Icon(Icons.access_time_filled),
          Icon(Icons.share_location),
          Icon(Icons.star_half),
        ],
      ),
    );
  }
}

image.png

GridView.count

GridView.count构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount,我们通过它可以快速的创建横轴固定数量子元素的GridView,例子:

GridView.count(
    crossAxisCount: 3,
    childAspectRatio: 1,
    children: const [
      Icon(Icons.ac_unit),
      Icon(Icons.apple),
      Icon(Icons.android),
      Icon(Icons.access_time_filled),
      Icon(Icons.share_location),
      Icon(Icons.star_half),
    ],
 ),

image.png

GridView.extent

GridView.extent构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent,我们通过它可以快速的创建横轴子元素为固定最大长度的的GridView,例子:

GridView.extent(
    maxCrossAxisExtent: 120,
    childAspectRatio: 2,
    children: const [
      Icon(Icons.ac_unit),
      Icon(Icons.apple),
      Icon(Icons.android),
      Icon(Icons.access_time_filled),
      Icon(Icons.share_location),
      Icon(Icons.star_half),
    ],
 ),

image.png

GridView.builder

当子widget比较多时,我们可以通过GridView.builder来动态创建子widgetGridView.builder 必须指定的参数有两个:

GridView.builder(
    gridDelegate: gridDelegate, 
    itemBuilder: itemBuilder
),

例子:

import 'package:flutter/material.dart';

class GridViewPage extends StatefulWidget {
  const GridViewPage({Key? key}) : super(key: key);
  @override
  State<GridViewPage> createState() => _GridViewPageState();
}

class _GridViewPageState extends State<GridViewPage> {
  final myProducts = List<Map>.generate(1000, (index) => {"id":index,"name":"P $index"}).toList();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView网格组件'),),
      body: GridView.builder(
        padding: const EdgeInsets.all(10),
        gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 200,
          childAspectRatio: 3/2,
          crossAxisSpacing: 20,
          mainAxisSpacing: 20
        ),
        itemCount: myProducts.length,
        itemBuilder: (BuildContext context,index){
          return Container(
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: Colors.amber,
              borderRadius: BorderRadius.circular(15),
            ),
            child: Text(myProducts[index]["name"]),
          );
        }
      ),
    );
  }
}

image.png