1. 前言
Flutter
作為時下最流行的技術(shù)之一悦陋,憑借其出色的性能以及抹平多端的差異優(yōu)勢,早已引起大批技術(shù)愛好者的關(guān)注认烁,甚至一些閑魚
,美團(tuán)
介汹,騰訊
等大公司均已投入生產(chǎn)使用却嗡。雖然目前其生態(tài)還沒有完全成熟,但身靠背后的Google
加持嘹承,其發(fā)展速度已經(jīng)足夠驚人窗价,可以預(yù)見將來對Flutter
開發(fā)人員的需求也會隨之增長。
無論是為了現(xiàn)在的技術(shù)嘗鮮還是將來的潮流趨勢叹卷,都9102年了撼港,作為一個前端開發(fā)者,似乎沒有理由不去嘗試它骤竹。正是帶著這樣的心理帝牡,筆者也開始學(xué)習(xí)Flutter
,同時建了一個用于練習(xí)的倉庫蒙揣,后續(xù)所有代碼都會托管在上面靶溜,歡迎star,一起學(xué)習(xí)懒震。這是我寫的Flutter系列文章:
- 用Flutter構(gòu)建漂亮的UI界面 - 基礎(chǔ)組件篇
- Flutter滾動型容器組件 - ListView篇
- Flutter網(wǎng)格型布局 - GridView篇
- 在Flutter中使用自定義Icon
經(jīng)過上一篇對ListView
組件的學(xué)習(xí)罩息,我們已經(jīng)對滾動型組件的使用有了初步認(rèn)識,這對今天要學(xué)習(xí)的GridView
組件十分有幫助个扰。因為兩者都繼承自BoxScrollView
扣汪,所以兩者的屬性有80%以上是相同的,用法非常相似锨匆。
而且如下圖所示可見崭别,GridView
網(wǎng)格布局在app中的使用頻率其實非常高冬筒,所以接下來就讓我們來看看在Flutter
中如何使用吧~
2. 初識GridView
今天我們的主角GridView
一共有5個構(gòu)造函數(shù):GridView
,GridView.builder
茅主,GridView.count
舞痰,GridView.extent
和GridView.custom
。但是不用慌诀姚,因為可以說其實掌握其默認(rèn)構(gòu)造函數(shù)就都會了~
來看下GridView
構(gòu)造函數(shù)(已省略不常用屬性):
GridView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required this.gridDelegate,
double cacheExtent,
List<Widget> children = const <Widget>[],
})
雖然又是一大堆屬性响牛,但是大部分都很熟悉,老朋友嘛~除了一個必填參數(shù)gridDelegate
外赫段,全和ListView
默認(rèn)構(gòu)造函數(shù)的參數(shù)一樣呀打,這也是文章開頭為什么說掌握了ListView
再學(xué)GridView
非常容易的原因。
那么接下來糯笙,就讓我們來重點關(guān)注下gridDelegate
這個參數(shù)贬丛,它其實是GridView
組件如何控制排列子元素的一個委托。跟蹤源碼我們可以在scroll_view.dart中看到给涕,gridDelegate
的類型是SliverGridDelegate
豺憔,進(jìn)一步跟蹤進(jìn)sliver_grid.dart可以看到SliverGridDelegate
其實是一個抽象類,而且一共有兩個實現(xiàn)類:
-
SliverGridDelegateWithFixedCrossAxisCount
:用于固定列數(shù)的場景够庙; -
SliverGridDelegateWithMaxCrossAxisExtent
:用于子元素有最大寬度限制的場景恭应;
2.1 SliverGridDelegateWithFixedCrossAxisCount
我們先來看下SliverGridDelegateWithFixedCrossAxisCount
,根據(jù)類名我們也能大概猜它是干什么用的:如果你的布局中每一行的列數(shù)是固定的
耘眨,那你就應(yīng)該用它昼榛。
來看下其構(gòu)造函數(shù):
SliverGridDelegateWithFixedCrossAxisCount({
@required this.crossAxisCount,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
-
crossAxisCount
:列數(shù),即一行有幾個子元素剔难; -
mainAxisSpacing
:主軸方向上的空隙間距褒纲; -
crossAxisSpacing
:次軸方向上的空隙間距; -
childAspectRatio
:子元素的寬高比例钥飞。
想必看到上面的示例圖莺掠,你就秒懂其中各個參數(shù)的含義了。不過读宙,這里有一點需要特別注意:如果你的子元素寬高比例不為1彻秆,那么你一定要設(shè)置childAspectRatio
屬性。
2.2 SliverGridDelegateWithMaxCrossAxisExtent
SliverGridDelegateWithMaxCrossAxisExtent
在實際應(yīng)用中可能會比較少结闸,來看下其構(gòu)造函數(shù):
SliverGridDelegateWithMaxCrossAxisExtent({
@required this.maxCrossAxisExtent,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
可以看到除了maxCrossAxisExtent
外唇兑,其他參數(shù)和SliverGridDelegateWithFixedCrossAxisCount
都是一樣的。那么maxCrossAxisExtent
是干什么的呢桦锄?我們來看個例子:
假如手機屏寬375
扎附,crossAxisSpacing
值為0
,
-
maxCrossAxisExtent
值為125
時结耀,網(wǎng)格列數(shù)將是3
留夜。因為125 * 3 = 375
匙铡,剛好,每一列的寬度就是375/3
碍粥。 -
maxCrossAxisExtent
值為126
時鳖眼,網(wǎng)格列數(shù)將是3
。因為126 * 3 > 375
嚼摩,顯示不下钦讳,每一列的寬度將是375/3
。 -
maxCrossAxisExtent
值為124
時枕面,網(wǎng)格列數(shù)將是4
愿卒。因為124 * 3 < 375
,仍有多余潮秘,每一列的寬度將是375/4
琼开。
可以看到,maxCrossAxisExtent
其實就是告訴GridView
組件子元素的最大寬度可能是多少唇跨,然后計算得到合適的列寬(實際上,我們也很少這么應(yīng)用衬衬,所以這種方法的使用頻率不高)买猖。
3. 實際應(yīng)用
經(jīng)過前面的介紹,我們已經(jīng)對GrdiView
組件有了初步了解滋尉,下面就來看看如何使用玉控。還記得之前GridView
的各種構(gòu)造函數(shù)嗎?其實:
-
GridView
默認(rèn)構(gòu)造函數(shù)可以類比于ListView
默認(rèn)構(gòu)造函數(shù)狮惜,適用于有限個數(shù)子元素的場景高诺,因為GridView
組件會一次性全部渲染children
中的子元素組件; -
GridView.builder
構(gòu)造函數(shù)可以類比于ListView.builder
構(gòu)造函數(shù)碾篡,適用于長列表的場景虱而,因為GridView
組件會根據(jù)子元素是否出現(xiàn)在屏幕內(nèi)而動態(tài)創(chuàng)建銷毀,減少內(nèi)存消耗开泽,更高效渲染牡拇; -
GridView.count
構(gòu)造函數(shù)是GrdiView
使用SliverGridDelegateWithFixedCrossAxisCount
的簡寫(語法糖),效果完全一致穆律; -
GridView.extent
構(gòu)造函數(shù)式GridView
使用SliverGridDelegateWithMaxCrossAxisExtent
的簡寫(語法糖)惠呼,效果完全一致。
先來看一個簡單的例子峦耘,它使用到GridView.count
構(gòu)造函數(shù)模仿美團(tuán)外賣首頁服務(wù)列表(服務(wù)菜單項的代碼可以看這里剔蹋,也算是對基礎(chǔ)組件使用的進(jìn)一步鞏固):
代碼(文件地址)
GridView.count(
crossAxisCount: 5,
padding: EdgeInsets.symmetric(vertical: 0),
children: serviceList.map((item) => ServiceItem(data: item)).toList(),
)
/*************/
/* 完全等同于 */
/************/
GridView(
padding: EdgeInsets.symmetric(vertical: 0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
),
children: serviceList.map((item) => ServiceItem(data: item)).toList(),
)
預(yù)覽
再來看一個模仿喜馬拉雅中相聲列表用到GridView.builder
創(chuàng)建網(wǎng)格布局的具體例子(相聲卡片的代碼可以看這里):
代碼(文件地址)
GridView.builder(
shrinkWrap: true,
itemCount: programmeList.length,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 16),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 0.7,
),
itemBuilder: (context, index) {
return Programme(data: programmeList[index]);
},
)
預(yù)覽
4. 總結(jié)
本文先是介紹了GridView
組件的屬性含義,并著重講解了SliverGridDelegateWithFixedCrossAxisCount
和SliverGridDelegateWithMaxCrossAxisExtent
分別適用的應(yīng)用場景辅髓。然后泣崩,通過兩個實際的應(yīng)用例子介紹了GridView
組件常用的構(gòu)造函數(shù)使用方法少梁。希望通過本文的介紹,你可以掌握Flutter
中網(wǎng)格型布局的使用~