Flutter学习笔记:GridView实现分组显示效果

前言部分

近期继续探索flutter的相关内容,这次介绍的控件是c,是使用率很高的的控件。以前我只是常规的使用其基本的用法,所以也没有做笔记,毕竟flutter中文网上还是有介绍的。

今天的需求稍微不同,需要通过GridView来显示一个列表。但是这个列表还需要有一个额外的功能就是分组。如果以前用Android实现的话,我们通常是使用RecyclerView来实现,可以通过多类型的ViewHolder来做,实现起来也是很简单。

那么在flutter中怎么实现呢?

先上图吧,按需使用。

内容部分

解答上面问题,分析如下。

  1. 我们使用GridView来实现一个两列的列表,如果加入一个分组条目,这个条目需要占满横排,所以GridView是否可以实现合并两个item?
  2. 如果实现不了我们有什么替代方案?
  • 其实上面的假设是不太容易实现,因为GridView本身是通过控制列数来实现的规则列表,我们的需求本身是有多类型的条目,所以不能适用我们的需求,需要另外找路来做。

flutter中文网在中文网在的最后的最后介绍了一个实现不规则的多列列表的例子传送

,例子中通过另外一个CustomScrollView.来实现多列的不规则列表。GitHub传送门

找到合适的例子,我们就可以开始学习使用了

通过了解项目,发现通过给每个item设置一个StaggeredTile类来控制每一个条目在列表中的大小占位。实际上StaggeredGridView的工作原理应该是,通过给每个item添加约束限制,在StaggeredGridView进行布局的时候通过读取item配置来进行布局,从而实现灵活的多列和多行的布局。就有点想很久以前winphone系统界面。

下面开始正式的使用一波

引入flutter_staggered_grid_view: ^0.3.0类库,然后在代码中使用极其简单。

代码如下:

new StaggeredGridView.countBuilder(
                      crossAxisCount: 2,
                      mainAxisSpacing: 4.0,
                      crossAxisSpacing: 4.0,
                      padding: const EdgeInsets.all(4.0),
                      itemCount: _mMainBean.length,
                      itemBuilder: (context, index) {
                        AccountData bean = _mMainBean[index];
                        return _getGridViewItemUI(context, bean, index);
                      },
                      controller: _scrollController,
                      staggeredTileBuilder: (int index) {
                        AccountData bean1 = _mMainBean[index];
                        if (bean1.cover == "title" && bean1.id != 1) {
                          return new StaggeredTile.count(2, 0.2);
                        } else {
                          return new StaggeredTile.count(1, 1);
                        }
                      },
                    ),                

上面就是构建好了的列表。

这里说明一下我的分列规律

这个Widget通过获取item的配置来进行布局,我通过把分组标识的数据添加到数据结合,然后在数据填充的时候进行过滤来识别出该数据,在布局中进行分类条目的布局。

我填充数据的规则如下

通过判断请求的数据长度是不是为单数,来确定是不是要填充一个空白的item。来保证我们的分类的标记item是完整的一行。

if (address.title.length % 2 == 0) {
              var accountData = AccountData();
              accountData.cover = "title";
              accountData.date = newTime;
              accountData.isLeft = true;
              _mMainBean.add(accountData);
              _mMainBean.addAll(address.title);
              
            } else {
              var accountData = AccountData();
              accountData.cover = "title";
              accountData.date = newTime;
              accountData.isLeft = true;
              _mMainBean.add(accountData);
              _mMainBean.addAll(address.title);

              var accountTemp = AccountData();
              accountTemp.cover = "title";
              accountTemp.date = newTime;
              accountTemp.id = 1;
              _mMainBean.add(accountTemp);
            }

填充布局的时候也要做一下区别,这就和android中的填充多条目一样了。代码如下:

 Widget _getGridViewItemUI(BuildContext context, AccountData city, int index) {
    if (city.cover == "title") {
      print(city.isLeft);
      if (city.id != 1) {
        return Container(
          margin: const EdgeInsets.only(left: 5, right: 5),
          child: Text(
            "----------- " + city.date.substring(5) + " 月 -----------",
            style: TextStyle(fontSize: 15, color: Colors.black38),
          ),
          alignment: Alignment.center,
        );
      } else {
        return Text("");
      }
    } else {
      return InkWell(
        onTap: () {
          Navigator.of(context).pop(index);
        },
        child: Card(
          elevation: 4.0,
          child: Column(
            children: [
              Image.network(
                city.cover,
                fit: BoxFit.cover,
              ),
              new Container(
                margin: const EdgeInsets.only(top: 20),
                child: Text(
                  city.date,
                  style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold),
                ),
              ),
            ],
          ),
        ),
      );
    }
  }

结尾部分

上面的就简单的实现了一个分组的效果,如果你有类似的效果,基本上可以直接套用的。

总体问题不难,不过由于flutter是新兴的框架,所以内容还是比较少见。

如果要看完整的效果就看一下我的项目吧

你可能感兴趣的:(Flutter)