美文网首页
Flutter小部件GridView

Flutter小部件GridView

作者: 程序员阿兵 | 来源:发表于2020-10-20 09:10 被阅读0次

    文章目录

    Flutter GridView

    网格布局在移动开发中也经常使用,Flutter 给我们提供了GridView供我们使用,下面我们来看看GridView的使用方法

    继承关系

    image.png

    构造方法

    GridView({
        Key key,
        Axis scrollDirection = Axis.vertical, 
        bool reverse = false,  
        ScrollController controller,
        bool primary,
        ScrollPhysics physics,
        bool shrinkWrap = false, 
        EdgeInsetsGeometry padding,  
        @required this.gridDelegate, 
        bool addAutomaticKeepAlives = true,
        bool addRepaintBoundaries = true,
        bool addSemanticIndexes = true,
        double cacheExtent,
        List<Widget> children = const <Widget>[],
        int semanticChildCount,
      })
    

    属性

    属性 值类型 说明
    scrollDirection Axis 设置滚动的方向,horizontal(水平)或vertical(垂直)
    reverse bool 是否翻转
    controller ScrollController 用来控制滚动位置及监听滚动事件
    shrinkWrap bool 是否根据子widget的总长度来设置GridView的长度
    padding EdgeInsetsGeometry 间距
    gridDelegate SliverGridDelegate 控制子Widget如何进行布局
    children List 子控件

    常用属性比较易懂,这里我们主要看一下gridDelegate

    gridDelegate

    该属性接收一个SliverGridDelegate类型的值,主要是用来控制子Widget如何进行布局。


    image.png

    他有如下两个实现类
    SliverGridDelegateWithMaxCrossAxisExtent和SliverGridDelegateWithFixedCrossAxisCount

    构造方法:

     const SliverGridDelegateWithMaxCrossAxisExtent({
        @required this.maxCrossAxisExtent, //子控件的最大宽度,实际宽度是根据交叉轴的值进行平分,也就是说最大宽度并不一定是实际宽度,很有可能子控件的实际宽度要小于设置的最大宽度
        this.mainAxisSpacing = 0.0, //主轴之间的间距
        this.crossAxisSpacing = 0.0,//交叉轴之间的间距
        this.childAspectRatio = 1.0,//子控件的宽高比
      }
    

    下面我们来简单用一用

    GridView(
          scrollDirection: Axis.vertical,
          gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 100, //子控件最大宽度为100
            childAspectRatio: 0.5,//宽高比为1:2
            crossAxisSpacing: 10,
            mainAxisSpacing: 10,
          ),
          padding: EdgeInsets.all(10),
          children: List.generate(
            20,
            (index) {
              return Box(index + 1);
            },
          ),
        );
    

    显示效果:


    image.png

    看了效果图我们可能会有疑问,我最大宽度设置的是110,那子控件为什么是4个呢

    首先我们先来看子控件的个数:

    子控件的个数实际上就是交叉轴的最大宽度除以我们设置的最大值得出的值,如果该值为整数,那个该值就是子控件的个数,如果不是整数,那么就舍掉小数点后面的值加上一后就是子控件的个数

    举个例子:

    假如交叉轴最大值为360,我们设置的最大值为89,那么子控件的个数就是5,如果我们设置的最大值为90,那么子控件的个数就是4,如果我们设置的最大值为91,那么子控件的个数也是4

    如果我们想明确的指定子控件的个数,我们可以这样写:

    maxCrossAxisExtent: MediaQuery.of(context).size.width/4,1
    

    MediaQuery.of(context).size.width就是屏幕的宽度,除以4,就是子控件的最大值,这样一来我们就可以确定要显示的子控件的个数了

    例如,我们更改一下滚动方向为横向滚动,此时交叉轴为垂直方向,那么最大值就是屏幕的高度。我们想让子控件个数为5,就可以这么写:

     maxCrossAxisExtent: MediaQuery.of(context).size.height/5,
    

    示例代码

    GridView(
          scrollDirection: Axis.horizontal,
          gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: MediaQuery.of(context).size.height/5,
            mainAxisSpacing: 10,
            crossAxisSpacing: 10,
          ),
          children: List.generate(
            20,
            (index) {
              return Box(index + 1);
            },
          ),
        );
    
    20190228155217426.gif

    SliverGridDelegateWithFixedCrossAxisCount

    理解了上面那个这个就很好理解了,就是设置交叉轴上子控件的个数

    构造方法:

    const SliverGridDelegateWithFixedCrossAxisCount({
        @required this.crossAxisCount,  //交叉轴上子控件的个数
        this.mainAxisSpacing = 0.0,
        this.crossAxisSpacing = 0.0,
        this.childAspectRatio = 1.0,
      }) 
    

    示例代码:

    GridView(
          scrollDirection: Axis.horizontal,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 6,
            mainAxisSpacing: 10,
            crossAxisSpacing: 10,
          ),
          children: List.generate(
            20,
            (index) {
              return Box(index + 1);
            },
          ),
        );
    
    image.png

    除了传统的构造方法外,GridView给我们提供更加方便的方法供我们使用

    GridView.count

    没什么好说的,跟上面的SliverGridDelegateWithFixedCrossAxisCount雷同
    示例代码:

    GridView.count(
          padding: EdgeInsets.all(10),
          crossAxisSpacing: 10,
          crossAxisCount: 3,
          mainAxisSpacing: 10,
          children: List.generate(
            20,
            (index) {
              return Box(index + 1);
            },
          ),
        );
    
    image.png

    GridView.extent

    跟SliverGridDelegateWithMaxCrossAxisExtent类似

    GridView.extent(
          scrollDirection: Axis.horizontal,
          maxCrossAxisExtent: MediaQuery.of(context).size.height/9,
          children: List.generate(
            20,
            (index) {
              return Box(index + 1);
            },
          ),
        );
    
    image.png

    Flutter GridView异步加载/加载更多(GridView.builder)

    跟构造方法使用方式差不多,主要是用来做异步数据加载的,前面几种方式都是在数据确定的情况下,实际上,我们的数据基本上都是从网络上获取的,有分页获取的需求,这个时候就用到GridView.builder了。

    首先看看源码:

    GridView.builder({
        Key key,
        Axis scrollDirection = Axis.vertical,
        bool reverse = false,
        ScrollController controller,
        bool primary,
        ScrollPhysics physics,
        bool shrinkWrap = false,
        EdgeInsetsGeometry padding,
        @required this.gridDelegate,
        @required IndexedWidgetBuilder itemBuilder,
        int itemCount,
        bool addAutomaticKeepAlives = true,
        bool addRepaintBoundaries = true,
        bool addSemanticIndexes = true,
        double cacheExtent,
        int semanticChildCount,
      })
    

    属性跟构造方法中的属性差不多,我们主要来看看itemCount和itemBuilder

    itemCount表示列表的数量,一般都是集合的长度
    itemBuilder是列表项构造器,返回一个Widget

    示例代码:

    import 'package:flutter/material.dart';
    
    /*
    * 
    * 网格布局
    * */
    class GridViewWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _GridViewVBuilder();
      }
    }
    
    class _GridViewVBuilder extends State<GridViewWidget> {
      List<int> indexs = List.generate(100, (index) {
        return index;
      });
    
      @override
      Widget build(BuildContext context) {
        return GridView.builder(
          gridDelegate:
              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
          itemCount: indexs.length,
          itemBuilder: (context, index) {
    
            /*当数据加载完毕时 追加数据*/
            if (index == indexs.length - 1 && indexs.length < 200) {
              _addIndex();
            }
    
            return Text(
              "$index",
              textAlign: TextAlign.center,
              style: TextStyle(
                color: Colors.red,
                fontSize: 20,
              ),
            );
          },
        );
      }
    
      void _addIndex() {
    
        /*这里要延时加载  否则会抱The widget on which setState() or markNeedsBuild() was called was:错误*/
        Future.delayed(Duration(milliseconds: 200)).then((e) {
          setState(() {
            indexs.add(indexs.length + 1);
          });
        });
      }
    }
    
    
    
    20190228173423222.gif

    好了,GridView基本用法大概就是这样。

    相关文章

      网友评论

          本文标题:Flutter小部件GridView

          本文链接:https://www.haomeiwen.com/subject/waikmktx.html