需求:

相信android和ios的瀑布流效果大家都试过,网上有很多实现方法和开源库,今天我来为大家介绍一下如何在Flutter中实现瀑布流,整理一下方便以后学习,顺便分享给大家。

一、生成二维码

1、导入依赖

在 pubspec.yaml 中 dependencies 节点下添加:

# 瀑布流插件
  flutter_staggered_grid_view: ^0.3.3
  # 网络缓存图片
  cached_network_image : ^0.6.2

2、引入代码

import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:cached_network_image/cached_network_image.dart';

3、创建方式

StaggeredGridView一共有6中创建方式:

StaggeredGridView.count()
StaggeredGridView.countBuilder()
StaggeredGridView.builder()
StaggeredGridView.custom()
StaggeredGridView.extent()
StaggeredGridView.extentBuilder()

StaggeredGridView.count():创建了一个纵轴方向固定Tile个数的布局,适合子Widget个数比较少的情况,使用List来设置。

StaggeredGridView.countBuilder():和StaggeredGridView.count()差不多,区别在于适合子Widget数量比较多,需要动态创建的情况。

StaggeredGridView.extent():创建了一个在纵轴方法指定Tile个数的最大值的布局,适合子Widget个数比较少的情况,使用List来设置。

StaggeredGridView.extentBuilder():和StaggeredGridView.extent()差不多,区别在于适合子Widget数量比较多,需要动态创建的情况。

StaggeredGridView.builder()和StaggeredGridView.custom()更高级也更灵活。

这里我们选择使用countBuilder

body: StaggeredGridView.countBuilder(
          crossAxisCount: 4,   //横轴单元格数量
          itemCount: 20,  //元素数量
          itemBuilder: (context,i){
             return new Material(
               elevation: 8.0,
               borderRadius: BorderRadius.all(Radius.circular(8.0)),
               child: new CachedNetworkImage(
                 imageUrl: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg1.yuntouxiang.com%2Fuploads%2F20130521%2F21-022304_646.jpg&refer=http%3A%2F%2Fimg1.yuntouxiang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1613615452&t=590bdef8fdbfb5c972066acbeca6543d",
                 imageBuilder: (context, imageProvider) => Container(
                   decoration: BoxDecoration(
                     borderRadius: BorderRadius.all(Radius.circular(8.0)),
                     image: DecorationImage(
                         image: imageProvider,
                         fit: BoxFit.fitHeight,
                         ),
                   ),
                 ),
               ),
             );
          },
          staggeredTileBuilder: (index){
            return StaggeredTile.count(2, index.isEven ? 2 : 1);  //第一个参数是横轴所占的单元数,第二个参数是主轴所占的单元数
          },
          padding: EdgeInsets.all(8),
          mainAxisSpacing: 8.0,
          crossAxisSpacing: 8.0,
      ),

itemBuilder是每个瀑布流的item,imageUrl可以改成数组,这样就可以显示不同的图片。crossAxisCount是指横轴总宽度被分为4份,总计四个单元格,itemCount指总元素数量

staggeredTileBuilder: (index){
            return StaggeredTile.count(2, index.isEven ? 2 : 1);  //第一个参数是横轴所占的单元数,第二个参数是主轴所占的单元数
          },

我设置每个item的宽度占2个单元格,这样就是一行两个,左右平分空间,高度偶数item为2,奇数为1,这个如果每个item高度都有不同高度的话,可以将item的高度用数组导入。

具体效果:

ios 瀑布流 头部 瀑布流软件_ios 瀑布流 头部

完整代码如下所示:

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:cached_network_image/cached_network_image.dart';

class Staggered extends StatefulWidget {
  @override
  _StaggeredState createState() => _StaggeredState();
}

class _StaggeredState extends State<Staggered> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("瀑布流"),
      ),
      body: StaggeredGridView.countBuilder(
          crossAxisCount: 4,   //横轴单元格数量
          itemCount: 20,  //元素数量
          itemBuilder: (context,i){
             return new Material(
               elevation: 8.0,
               borderRadius: BorderRadius.all(Radius.circular(8.0)),
               child: new CachedNetworkImage(
                 imageUrl: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg1.yuntouxiang.com%2Fuploads%2F20130521%2F21-022304_646.jpg&refer=http%3A%2F%2Fimg1.yuntouxiang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1613615452&t=590bdef8fdbfb5c972066acbeca6543d",
                 imageBuilder: (context, imageProvider) => Container(
                   decoration: BoxDecoration(
                     borderRadius: BorderRadius.all(Radius.circular(8.0)),
                     image: DecorationImage(
                         image: imageProvider,
                         fit: BoxFit.fitHeight,
                         ),
                   ),
                 ),
               ),
             );
          },
          staggeredTileBuilder: (index){
            return StaggeredTile.count(2, index.isEven ? 2 : 1);  //第一个参数是横轴所占的单元数,第二个参数是主轴所占的单元数
          },
          padding: EdgeInsets.all(8),
          mainAxisSpacing: 8.0,
          crossAxisSpacing: 8.0,
      ),
    );
  }
}