Flutter实现瀑布流效果(GridView部件不固定高度)

Flutter实现瀑布流效果

  • 引言
    • 安装 flutter_staggered_grid_view
    • 布局中使用 flutter_staggered_grid_view
      • card_page.dart 父级页面
      • square_card_item.dart 子部件
      • 卡片数据模型

引言

Flutter APP 中实现瀑布流布局展示商品信息。效果图:

安装 flutter_staggered_grid_view

Flutter自带的网格布局部件固定了每个子部件的高度,不能实现我们的需求。GridView 部件:如下图所示:

Flutter实现瀑布流效果(GridView部件不固定高度)_第1张图片
要想实现瀑布流效果需要使用第三方包: flutter_staggered_grid_view

布局中使用 flutter_staggered_grid_view

为了便于代码的阅读和拓展,减少嵌套理清业务逻辑(文邹邹的理论。。。),实际上就是把 GridView部件的父级页面和他的子项布局写在两个文件里面。

card_page.dart 父级页面

这里面主要实例化封装好的 Dio 类来请求获取商品数据和编写父别页面布局。

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:oblivion/public.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:oblivion/widgets/square_card.dart';
import 'package:oblivion/model/CardModel.dart';


class CardPage extends StatefulWidget {
  @override
  _CardPageState createState() => _CardPageState();
}

class _CardPageState extends State<CardPage> {
  List cardList;
  //获取商品数据
  Future getSquarePageContent() async{
    DioManager.getInstance().postNoParams(ServiceUrl.getCards,(data) {
      setState(() {
      	//商品列表
        cardList =(data['data']['cards'] as List).cast();
      });
    }, (error) {
      print("接口异常:" + error);
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    getSquarePageContent();
    super.initState();
  }
  //下拉刷新方法
  Future<void> _onRefresh() async {
    print("_onRefresh");
  }
  //上拉加载方法
  Future<void> _onLoadMore() async {
    print("_onLoadMore");
  }
  @override
  Widget build(BuildContext context) {
    if(cardList == null){
      return Text('没有数据');
    }else{
      return Container(
        height: ScreenUtil().setHeight(1500),
        padding:EdgeInsets.all(3.0),
        child:  StaggeredGridView.countBuilder(
          padding: EdgeInsets.all(8),
          crossAxisCount: 4,
          itemCount: cardList.length,
          //核心代码,将Cards模型对象作为参数传递                                                                                                                                                                                                                                                             
          itemBuilder: (BuildContext context, int index) {
            var item = new Cards.fromJson(cardList[index]);
            return CardItem(item);
          },
          staggeredTileBuilder: (index) => StaggeredTile.fit(2),
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
        ),
      );
    }
  }
}

square_card_item.dart 子部件

这部分主要从数据模型取出数据,编写每一个子项的页面布局。

import 'package:flutter/material.dart';
import 'package:oblivion/model/CardModel.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:transparent_image/transparent_image.dart';
class CardItem extends StatefulWidget {

  CardItem(this.item);

  final Cards item;

  @override
  _CardItemState createState() {
    return _CardItemState();
  }
}

class _CardItemState extends State<CardItem> {

  _CardItemState();

  @override
  Widget build(BuildContext context) {
    return Card(
        child: InkWell(
          onTap: (){
            // 跳转到商品详情
            print('点击了一件商品');
          },
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              // 图片
              Container(
                  width: double.infinity,
                  color: Colors.grey,
                  child:FadeInImage.assetNetwork(
                    placeholder: 'assets/images/loader.gif',
                    image: widget.item.img,//这里是网络图片
                    fit: BoxFit.fill,
                  ),
              ),
              // 描述
              Container(
                  padding: EdgeInsets.fromLTRB(5, 5, 5, 0),
                  child: Text(widget.item.des,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                  )
              ),

              Container(
                height: ScreenUtil().setHeight(80),
                  padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
                  child: Align(
                    alignment: Alignment.bottomLeft,
                    heightFactor: 2,
                    widthFactor: 2,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        // 价钱和想要人数
                        Text("¥${widget.item.price.toString()}",style:TextStyle(color:Colors.pink)),
                        Text("${widget.item.want.toString()}人想要",style:TextStyle(fontSize: 10)),
                      ],
                    ),
                  ),
              ),
              Padding(
                  padding: EdgeInsets.all(1.0),
                  child: new Divider()
              ),
              Container(
                height: ScreenUtil().setHeight(160),
                padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
                child: Align(
                  alignment: Alignment.bottomLeft,
                  heightFactor: 2,
                  widthFactor: 2,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
                      // 价钱和想要
                      Padding(
                        padding: EdgeInsets.only(top: 6),
                        child: Column(
                          children: <Widget>[
                            Image.network(
                              widget.item.img,
                              fit: BoxFit.fill,
                              height: ScreenUtil().setHeight(110),
                              width: ScreenUtil().setWidth(80),
                            ),
                          ],
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(6, 0, 0, 0),
                        child: Center(
                           child: Text(widget.item.username,style:TextStyle(color:Colors.black)),
                        ),
                      )

                    ],
                  ),
                ),
              ),
            ],
          ),
        )
    );
  }
}

卡片数据模型

class CardModel {
  List<Cards> _cards;

  CardModel({List<Cards> cards}) {
    this._cards = cards;
  }

  List<Cards> get cards => _cards;
  set cards(List<Cards> cards) => _cards = cards;

  CardModel.fromJson(Map<String, dynamic> json) {
    if (json['cards'] != null) {
      _cards = new List<Cards>();
      json['cards'].forEach((v) {
        _cards.add(new Cards.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this._cards != null) {
      data['cards'] = this._cards.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Cards {
  String _img;
  String _des;
  int _price;
  int _want;
  String _username;

  Cards({String img, String des, int price, int want, String username}) {
    this._img = img;
    this._des = des;
    this._price = price;
    this._want = want;
    this._username = username;
  }

  String get img => _img;
  set img(String img) => _img = img;
  String get des => _des;
  set des(String des) => _des = des;
  int get price => _price;
  set price(int price) => _price = price;
  int get want => _want;
  set want(int want) => _want = want;
  String get username => _username;
  set username(String username) => _username = username;

  Cards.fromJson(Map<String, dynamic> json) {
    _img = json['img'];
    _des = json['des'];
    _price = json['price'];
    _want = json['want'];
    _username = json['username'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['img'] = this._img;
    data['des'] = this._des;
    data['price'] = this._price;
    data['want'] = this._want;
    data['username'] = this._username;
    return data;
  }
}

JSON格式

{
	"cards": [{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_1.jpg",
			"des": "美国短毛猫是原产于美国的一种猫,其祖先为欧洲早期移民带到北美的猫种,并与英国短毛猫和欧洲短毛猫同类。美国短毛猫的身体匀称、有力量,且活泼温顺。幼年短毛猫圆头圆脑,软绵绵的手感和灵活的四肢很是讨人喜欢",
			"price": 111.00,
			"want": 122,
			"username": "美羊羊"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_2.jpg",
			"des": "布偶猫是猫中较大、较重的一种。它的头呈V形,眼大而圆,被毛丰厚,四肢粗大,尾长,身体柔软,多为三色或双色猫。",
			"price": 111.00,
			"want": 1000,
			"username": "小窝"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_3.jpg",
			"des": "布偶猫是猫中较大、较重的一种。它的头呈V形,眼大而圆,被毛丰厚,四肢粗大,尾长,身体柔软,多为三色或双色猫。",
			"price": 111.00,
			"want": 122,
			"username": "海绵宝宝"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_4.jpg",

			"des": "美国短毛猫是原产于美国的一种猫,其祖先为欧洲早期移民带到北美的猫种,并与英国短毛猫和欧洲短毛猫同类。美国短毛猫的身体匀称、有力量,且活泼温顺。幼年短毛猫圆头圆脑,软绵绵的手感和灵活的四肢很是讨人喜欢",
			"price": 111.00,
			"want": 122,
			"username": "流传风"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_5.jpg",
			"des": "美国短毛猫是原产于美国的一种猫,其祖先为欧洲早期移民带到北美的猫种,并与英国短毛猫和欧洲短毛猫同类。美国短毛猫的身体匀称、有力量,且活泼温顺。幼年短毛猫圆头圆脑,软绵绵的手感和灵活的四肢很是讨人喜欢",
			"price": 111.00,
			"want": 122,
			"username": "大发明家"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_6.jpg",
			"des": "美国短毛猫是原产于美国的一种猫,其祖先为欧洲早期移民带到北美的猫种,并与英国短毛猫和欧洲短毛猫同类。美国短毛猫的身体匀称、有力量,且活泼温顺。幼年短毛猫圆头圆脑,软绵绵的手感和灵活的四肢很是讨人喜欢",
			"price": 111.00,
			"want": 122,
			"username": "冰封凤凰"
		},
		{
			"img": "http://scrutiny.geekadpt.cn/v1/images/card_1.jpg",
			"des": "美国短毛猫是原产于美国的一种猫,其祖先为欧洲早期移民带到北美的猫种,并与英国短毛猫和欧洲短毛猫同类。美国短毛猫的身体匀称、有力量,且活泼温顺。幼年短毛猫圆头圆脑,软绵绵的手感和灵活的四肢很是讨人喜欢",
			"price": 111.00,
			"want": 122,
			"username": "宇宙星神"
		}
	]
}

你可能感兴趣的:(Flutter软件开发,Flutter,GridView,瀑布流)