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

引言

Flutter APP 中實現瀑布流佈局展示商品信息。效果圖:

在這裏插入圖片描述

安裝 flutter_staggered_grid_view

Flutter自帶的網格佈局部件固定了每個子部件的高度,不能實現我們的需求。GridView 部件:如下圖所示:

在這裏插入圖片描述
要想實現瀑布流效果需要使用第三方包: 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": "宇宙星神"
		}
	]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章