經一位前輩提點,問了一個在Flutter中如何實現瀑布流效果的問題。能力有限,本身實在沒法徒手造輪子實現。只能求助github,萬幸找到了一個開源的flutter_staggered_grid_view。發現相關資料不多,寫篇文章小小的解讀一下。git
dependencies:
flutter_staggered_grid_view: x.x.x
複製代碼
//在終端執行命令
flutter pub get
複製代碼
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.count
和StaggeredGridView.extent
,前者建立了一個在縱軸方向有固定數量子View的佈局,後者相似,只是指定了縱軸方向View數量的最大值。可是這兩個東西只適合用在子View數量較少且固定的場景下,他們都是經過一個List<Widget>
接收固定數量的子佈局。StaggeredGridView.builder
、StaggeredGridView.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