Flutter網(wǎng)格型布局 - GridView篇

1. 前言

Flutter作為時下最流行的技術之一,憑借其出色的性能以及抹平多端的差異優(yōu)勢,早已引起大批技術愛好者的關注,甚至一些閑魚,美團,騰訊等大公司均已投入生產(chǎn)使用。雖然目前其生態(tài)還沒有完全成熟,但身靠背后的Google加持,其發(fā)展速度已經(jīng)足夠驚人,可以預見將來對Flutter開發(fā)人員的需求也會隨之增長。

無論是為了現(xiàn)在的技術嘗鮮還是將來的潮流趨勢,都9102年了,作為一個前端開發(fā)者,似乎沒有理由不去嘗試它。正是帶著這樣的心理,筆者也開始學習Flutter,同時建了一個用于練習的倉庫,后續(xù)所有代碼都會托管在上面,歡迎star,一起學習。這是我寫的Flutter系列文章:

經(jīng)過上一篇ListView組件的學習,我們已經(jīng)對滾動型組件的使用有了初步認識,這對今天要學習的GridView組件十分有幫助。因為兩者都繼承自BoxScrollView,所以兩者的屬性有80%以上是相同的,用法非常相似。

而且如下圖所示可見,GridView網(wǎng)格布局在app中的使用頻率其實非常高,所以接下來就讓我們來看看在Flutter中如何使用吧~

app中網(wǎng)格布局的使用

2. 初識GridView

今天我們的主角GridView一共有5個構造函數(shù):GridViewGridView.builder,GridView.count,GridView.extentGridView.custom。但是不用慌,因為可以說其實掌握其默認構造函數(shù)就都會了~

來看下GridView構造函數(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默認構造函數(shù)的參數(shù)一樣,這也是文章開頭為什么說掌握了ListView再學GridView非常容易的原因。

那么接下來,就讓我們來重點關注下gridDelegate這個參數(shù),它其實是GridView組件如何控制排列子元素的一個委托。跟蹤源碼我們可以在scroll_view.dart中看到,gridDelegate的類型是SliverGridDelegate,進一步跟蹤進sliver_grid.dart可以看到SliverGridDelegate其實是一個抽象類,而且一共有兩個實現(xiàn)類:

  • SliverGridDelegateWithFixedCrossAxisCount:用于固定列數(shù)的場景;
  • SliverGridDelegateWithMaxCrossAxisExtent:用于子元素有最大寬度限制的場景;

2.1 SliverGridDelegateWithFixedCrossAxisCount

我們先來看下SliverGridDelegateWithFixedCrossAxisCount,根據(jù)類名我們也能大概猜它是干什么用的:如果你的布局中每一行的列數(shù)是固定的,那你就應該用它。

來看下其構造函數(shù):

SliverGridDelegateWithFixedCrossAxisCount({
  @required this.crossAxisCount,
  this.mainAxisSpacing = 0.0,
  this.crossAxisSpacing = 0.0,
  this.childAspectRatio = 1.0,
})
  • crossAxisCount:列數(shù),即一行有幾個子元素;
  • mainAxisSpacing:主軸方向上的空隙間距;
  • crossAxisSpacing:次軸方向上的空隙間距;
  • childAspectRatio:子元素的寬高比例。
屬性解釋

想必看到上面的示例圖,你就秒懂其中各個參數(shù)的含義了。不過,這里有一點需要特別注意:如果你的子元素寬高比例不為1,那么你一定要設置childAspectRatio屬性。

2.2 SliverGridDelegateWithMaxCrossAxisExtent

SliverGridDelegateWithMaxCrossAxisExtent在實際應用中可能會比較少,來看下其構造函數(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組件子元素的最大寬度可能是多少,然后計算得到合適的列寬(實際上,我們也很少這么應用,所以這種方法的使用頻率不高)。

3. 實際應用

經(jīng)過前面的介紹,我們已經(jīng)對GrdiView組件有了初步了解,下面就來看看如何使用。還記得之前GridView的各種構造函數(shù)嗎?其實:

  1. GridView默認構造函數(shù)可以類比于ListView默認構造函數(shù),適用于有限個數(shù)子元素的場景,因為GridView組件會一次性全部渲染children中的子元素組件;
  2. GridView.builder構造函數(shù)可以類比于ListView.builder構造函數(shù),適用于長列表的場景,因為GridView組件會根據(jù)子元素是否出現(xiàn)在屏幕內而動態(tài)創(chuàng)建銷毀,減少內存消耗,更高效渲染;
  3. GridView.count構造函數(shù)是GrdiView使用SliverGridDelegateWithFixedCrossAxisCount的簡寫(語法糖),效果完全一致;
  4. GridView.extent構造函數(shù)式GridView使用SliverGridDelegateWithMaxCrossAxisExtent的簡寫(語法糖),效果完全一致。

先來看一個簡單的例子,它使用到GridView.count構造函數(shù)模仿美團外賣首頁服務列表(服務菜單項的代碼可以看這里,也算是對基礎組件使用的進一步鞏固):

代碼(文件地址

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創(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]);
  },
)

預覽

喜馬拉雅 - 相聲列表

4. 總結

本文先是介紹了GridView組件的屬性含義,并著重講解了SliverGridDelegateWithFixedCrossAxisCountSliverGridDelegateWithMaxCrossAxisExtent分別適用的應用場景。然后,通過兩個實際的應用例子介紹了GridView組件常用的構造函數(shù)使用方法。希望通過本文的介紹,你可以掌握Flutter中網(wǎng)格型布局的使用~

本文所有代碼托管在這兒,也可以關注我的Blog,歡迎一起交流學習~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 本文對Flutter的29種布局控件進行了總結分類,講解一些布局上的優(yōu)化策略,以及面對具體的布局時,如何去選擇控件...
    Q吹個大氣球Q閱讀 10,813評論 15 153
  • 1. 前言 Flutter作為時下最流行的技術之一,憑借其出色的性能以及抹平多端的差異優(yōu)勢,早已引起大批技術愛好者...
    小石頭若海閱讀 15,169評論 3 27
  • 國慶后面兩天在家學習整理了一波flutter,基本把能擼過能看到的代碼都過了一遍,此文篇幅較長,建議保存(star...
    Nealyang閱讀 4,453評論 1 17
  • 本文對Flutter的29種布局控件進行了總結分類,講解一些布局上的優(yōu)化策略,以及面對具體的布局時,如何去選擇控件...
    chilim閱讀 1,339評論 0 19
  • 回想中找到回家的路 我還在尋求答案,我回想起自己的身世:我是個孤兒,我雖然有父母、有家人、有家,但我知道,他們不是...
    本體悅閱讀 310評論 0 1

友情鏈接更多精彩內容