Flutter
做爲時下最流行的技術之一,憑藉其出色的性能以及抹平多端的差別優點,早已引發大批技術愛好者的關注,甚至一些閒魚
,美團
,騰訊
等大公司均已投入生產使用。雖然目前其生態尚未徹底成熟,但身靠背後的Google
加持,其發展速度已經足夠驚人,能夠預見未來對Flutter
開發人員的需求也會隨之增加。前端
不管是爲了如今的技術嚐鮮仍是未來的潮流趨勢,都9102年了,做爲一個前端開發者,彷佛沒有理由不去嘗試它。正是帶着這樣的心理,筆者也開始學習Flutter
,同時建了一個用於練習的倉庫,後續全部代碼都會託管在上面,歡迎star,一塊兒學習。這是我寫的Flutter系列文章:git
通過上一篇對ListView
組件的學習,咱們已經對滾動型組件的使用有了初步認識,這對今天要學習的GridView
組件十分有幫助。由於二者都繼承自BoxScrollView
,因此二者的屬性有80%以上是相同的,用法很是類似。github
並且以下圖所示可見,GridView
網格佈局在app中的使用頻率其實很是高,因此接下來就讓咱們來看看在Flutter
中如何使用吧~markdown
今天咱們的主角GridView
一共有5個構造函數:GridView
,GridView.builder
,GridView.count
,GridView.extent
和GridView.custom
。可是不用慌,由於能夠說其實掌握其默認構造函數就都會了~app
來看下GridView
構造函數(已省略不經常使用屬性):函數
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>[],
})
複製代碼
雖然又是一大堆屬性,可是大部分都很熟悉,老朋友嘛~除了一個必填參數gridDelegate
外,全和ListView
默認構造函數的參數同樣,這也是文章開頭爲何說掌握了ListView
再學GridView
很是容易的緣由。佈局
那麼接下來,就讓咱們來重點關注下gridDelegate
這個參數,它實際上是GridView
組件如何控制排列子元素的一個委託。跟蹤源碼咱們能夠在scroll_view.dart中看到,gridDelegate
的類型是SliverGridDelegate
,進一步跟蹤進sliver_grid.dart能夠看到SliverGridDelegate
實際上是一個抽象類,並且一共有兩個實現類:post
SliverGridDelegateWithFixedCrossAxisCount
:用於固定列數的場景;SliverGridDelegateWithMaxCrossAxisExtent
:用於子元素有最大寬度限制的場景;咱們先來看下SliverGridDelegateWithFixedCrossAxisCount
,根據類名咱們也能大概猜它是幹什麼用的:若是你的佈局中每一行的列數是固定的
,那你就應該用它。性能
來看下其構造函數:學習
SliverGridDelegateWithFixedCrossAxisCount({
@required this.crossAxisCount,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
複製代碼
crossAxisCount
:列數,即一行有幾個子元素;mainAxisSpacing
:主軸方向上的空隙間距;crossAxisSpacing
:次軸方向上的空隙間距;childAspectRatio
:子元素的寬高比例。想必看到上面的示例圖,你就秒懂其中各個參數的含義了。不過,這裏有一點須要特別注意:若是你的子元素寬高比例不爲1,那麼你必定要設置childAspectRatio
屬性。
SliverGridDelegateWithMaxCrossAxisExtent
在實際應用中可能會比較少,來看下其構造函數:
SliverGridDelegateWithMaxCrossAxisExtent({
@required this.maxCrossAxisExtent,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
複製代碼
能夠看到除了maxCrossAxisExtent
外,其餘參數和SliverGridDelegateWithFixedCrossAxisCount
都是同樣的。那麼maxCrossAxisExtent
是幹什麼的呢?咱們來看個例子:
假如手機屏寬375
,crossAxisSpacing
值爲0
,
maxCrossAxisExtent
值爲125
時,網格列數將是3
。由於125 * 3 = 375
,恰好,每一列的寬度就是375/3
。maxCrossAxisExtent
值爲126
時,網格列數將是3
。由於126 * 3 > 375
,顯示不下,每一列的寬度將是375/3
。maxCrossAxisExtent
值爲124
時,網格列數將是4
。由於124 * 3 < 375
,仍有多餘,每一列的寬度將是375/4
。能夠看到,maxCrossAxisExtent
其實就是告訴GridView
組件子元素的最大寬度多是多少,而後計算獲得合適的列寬(實際上,咱們也不多這麼應用,因此這種方法的使用頻率不高)。
通過前面的介紹,咱們已經對GrdiView
組件有了初步瞭解,下面就來看看如何使用。還記得以前GridView
的各類構造函數嗎?其實:
GridView
默認構造函數能夠類比於ListView
默認構造函數,適用於有限個數子元素的場景,由於GridView
組件會一次性所有渲染children
中的子元素組件;GridView.builder
構造函數能夠類比於ListView.builder
構造函數,適用於長列表的場景,由於GridView
組件會根據子元素是否出如今屏幕內而動態建立銷燬,減小內存消耗,更高效渲染;GridView.count
構造函數是GrdiView
使用SliverGridDelegateWithFixedCrossAxisCount
的簡寫(語法糖),效果徹底一致;GridView.extent
構造函數式GridView
使用SliverGridDelegateWithMaxCrossAxisExtent
的簡寫(語法糖),效果徹底一致。先來看一個簡單的例子,它使用到GridView.count
構造函數模仿美團外賣首頁服務列表(服務菜單項的代碼能夠看這裏,也算是對基礎組件使用的進一步鞏固):
代碼(文件地址)
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(),
)
複製代碼
預覽
再來看一個模仿喜馬拉雅中相聲列表用到GridView.builder
建立網格佈局的具體例子(相聲卡片的代碼能夠看這裏):
代碼(文件地址)
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]);
},
)
複製代碼
預覽
本文先是介紹了GridView
組件的屬性含義,並着重講解了SliverGridDelegateWithFixedCrossAxisCount
和SliverGridDelegateWithMaxCrossAxisExtent
分別適用的應用場景。而後,經過兩個實際的應用例子介紹了GridView
組件經常使用的構造函數使用方法。但願經過本文的介紹,你能夠掌握Flutter
中網格型佈局的使用~