flutter_staggered_grid_view和瀑布流效果

前言

經一位前輩提點,問了一個在Flutter中如何實現瀑布流效果的問題。能力有限,本身實在沒法徒手造輪子實現。只能求助github,萬幸找到了一個開源的flutter_staggered_grid_view。發現相關資料不多,寫篇文章小小的解讀一下。git

配置

  1. 添加依賴:
dependencies:
  flutter_staggered_grid_view: x.x.x
複製代碼
  1. 安裝
//在終端執行命令
flutter pub get
複製代碼
  1. 導包
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
複製代碼

以後使用StaggeredGridView這個Widget就能夠實現了。 Pub官網接入教程 注意:若是遇到Unhandled Exception: type 'SliverHitTestResult' is not a subtype of type 'BoxHitTestResult'異常,請檢查flutter_staggered_grid_view版本,並嘗試升級。參考#49github

使用

直接貼一段flutter_staggered_grid_view上的代碼(我給加點註釋):bash

new StaggeredGridView.countBuilder(
  crossAxisCount: 4,
  itemCount: 8,
  itemBuilder: (BuildContext context, int index) => new Container(
      color: Colors.green,
      child: new Center(
        child: new CircleAvatar(
          backgroundColor: Colors.white,
          child: new Text('$index'),
        ),
      )),
  staggeredTileBuilder: (int index) =>
      new StaggeredTile.count(2, index.isEven ? 2 : 1),
  mainAxisSpacing: 4.0,
  crossAxisSpacing: 4.0,
)
複製代碼

其效果以下: dom

仔細看看這段代碼,基本都好理解:裏面放了八個子widget,主軸和縱軸方向的( 主軸和縱軸?)間距都是4個像素; staggeredTileBuilder好像是根據奇偶數控制子VIew的大小。 crossAxisCount就比較奇怪,按照字面意思是縱軸方向view的個數,代碼裏命名賦值爲4,可跑起來怎麼只有兩列?

粗讀源碼

首先看一下StaggeredGridView,它的構造方法有如下幾種: ide

閱讀官方的註釋以後,個人理解爲:

  • 最經常使用的是StaggeredGridView.countStaggeredGridView.extent,前者建立了一個在縱軸方向有固定數量子View的佈局,後者相似,只是指定了縱軸方向View數量的最大值。可是這兩個東西只適合用在子View數量較少且固定的場景下,他們都是經過一個List<Widget>接收固定數量的子佈局。
  • 若是要建立含有大量子佈局的網格視圖,就要使用StaggeredGridView.builderStaggeredGridView.countBuilder或者 StaggeredGridView.extentBuilder。更高級的是自定義SliverVariableSizeChildDelegate一個,而後經過StaggeredGridView.custom建立佈局。 前者的使用方法爲: 以StaggeredGridView.count爲例,其使用方法爲:
StaggeredGridView
		.count(
          crossAxisCount: 4,
          mainAxisSpacing: 2,
          crossAxisSpacing: 2,
          children: <Widget>[
            item(1),
           	...
            item(13),
          ],
          staggeredTiles: const <StaggeredTile>[
            const StaggeredTile.count(2, 1),
           	...
            const StaggeredTile.count(2, 1),
            const StaggeredTile.count(2, 2),
            ...
            const StaggeredTile.count(2, 2),
          ],
        )
複製代碼

其效果爲: 佈局

先來分析一下上文中說到的問題—— crossAxisCount。 翻看源碼發現 crossAxisCount在類 SliverStaggeredGridDelegateWithFixedCrossAxisCount中,並有一條註釋: The number of children in the cross axis.。根據註釋仍是感受這個屬性是用來指定縱軸方向Item的個數的,依然是沒法解釋上文中命名傳入的是4卻只有兩列的問題。這時,我在做者提交的 README文件發現了下面一段話:
我理解的大體意思就是: StaggeredGridView須要知道每一個子佈局(tile)如何去顯示,以及這些tile裏是什麼樣的Widget。而這些 tile須要在軸上佔有固定數量的單元格。還有三種方式供咱們去配置戰友的單元格數量,一種是指定數量,一種是指定最大值範圍,還有一張是動態的,由tile裏widget自身決定。 注意 tile須要在軸上佔有固定數量的單元格。這句話,一切都明瞭了, crossAxisCount並非設置的軸上有幾個佈局,而是將根佈局(或者說屏幕)分爲幾個單元格,而後經過 staggeredTileBuilder去指定每一個佈局佔據幾個單元格。而配置方式就是經過 StaggeredTile的單個構造方法:

  • StaggeredTile.count:固定數量
  • StaggeredTile.extent:最大值範圍
  • StaggeredTile.fit:自適應內容 這樣上面的問題就能夠理解了,網格列數由兩個屬性決定,也能夠加單粗暴的理解爲:列數 = crossAxisCount / StaggeredTile指定的佔據幾個單元格。

瀑布流效果

flutter_staggered_grid_view有了基本的瞭解以後,咱們再去實現一個瀑布流:post

@override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Container(
      color: Colors.white,
      child: new Container(
        width: 200,
        color: Colors.amberAccent,
        child: new StaggeredGridView.countBuilder(
          //滑動控制器
          controller: _scrollController,
          primary: false,
          //滑動方向
          scrollDirection: Axis.vertical,
          //縱軸方向被劃分的個數
          crossAxisCount: 2,
          //item的數量
          itemCount: 12,
          /**
           * mainAxisSpacing:主軸item之間的距離(px)
           * crossAxisSpacing:縱軸item之間的距離(px)
           * */
          mainAxisSpacing: 2.0,
          crossAxisSpacing: 2.0,
          staggeredTileBuilder: (index) => StaggeredTile.fit(1),
          itemBuilder: (BuildContext context, int index) => new Container(
            color: Colors.green,
            //隨機生成高度
            height: 100 + Random().nextInt(10) * 20.0,
            width: 20,
            child: new Center(
              child: new CircleAvatar(
                backgroundColor: Colors.white,
                child: new Text('$index'),
              ),
            ),
          ),
        ),
      ),
    );
  }
複製代碼

效果以下: ui

終於有點瀑布流的樣子了,

總結

德淺才疏,若有紕漏和不足,請你們指出,萬分感謝 spa

相關文章
相關標籤/搜索