作者 | 弗拉德
來源 | 弗拉德(公眾號:fulade_me)
GridView
GridView 是一個好用的網(wǎng)格布局控件,它的很多屬性跟前面提到的ListView是一樣的,重復的屬性這里就不贅述了。我們重點了解初始化方法GridView.count的使用,還有兩個代理SliverGridDelegateWithFixedCrossAxisCount、SliverGridDelegateWithMaxCrossAxisExtent的參數(shù)以及使用。
GridView.count
我們先來看GridView.count的構(gòu)造函數(shù)
GridView.count({
/// key
Key key,
/// 布局方向
Axis scrollDirection = Axis.vertical,
/// 是否 倒序顯示
bool reverse = false,
/// ScrollController用于控制滾動位置和監(jiān)聽滾動事件
ScrollController controller,
/// 是否使用默認的controller
bool primary,
/// 滾動效果 可以通過此參數(shù) 設置 GridView 不可滾動
ScrollPhysics physics,
/// 是否根據(jù)子控件的總長度來設置 GridView 的長度,默認值為false
bool shrinkWrap = false,
/// padding
EdgeInsetsGeometry padding,
/// 交叉軸 子控件的個數(shù)
@required int crossAxisCount,
/// 主軸方向的間距
double mainAxisSpacing = 0.0,
/// 交叉軸方向子元素的間距
double crossAxisSpacing = 0.0,
/// 子控件的寬高比例
double childAspectRatio = 1.0,
// 在 關(guān)閉屏幕時 是否釋放子控件
bool addAutomaticKeepAlives = true,
/// 是否 避免列表項重繪
bool addRepaintBoundaries = true,
/// 該屬性表示是否把子控件包裝在IndexedSemantics里,用來提供無障礙語義
bool addSemanticIndexes = true,
// 預加載子控件的個數(shù)
double cacheExtent,
/// 子控件的數(shù)組
List<Widget> children = const <Widget>[],
/// 子控件的數(shù)量
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
})
這里要說的是有兩個比較重要的參數(shù)crossAxisSpacing和childAspectRatio,這個兩個參數(shù)是用來定義子控件大小的。
假如我們設置 crossAxisSpacing = 2,那么每一行就會顯示2個控件,而且控件的高度由childAspectRatio來確定。
childAspectRatio表示子控件的寬高比,假如我們設置為2 / 3,那么高就是寬的1.5倍,這樣就可以計算子控件的大小了,并且按照 GridView設置好的方向來排列和布局子控件。
GridView.count(
crossAxisCount: 3,
childAspectRatio: 2 / 3,
children: List.generate(
50,
(index) {
return Card(
child: Container(
color: Colors.green,
child: Center(
child: Text("$index"),
),
),
);
},
),
)
效果圖如下:

SliverGridDelegateWithFixedCrossAxisCount
除了GridView.count()這種構(gòu)造方法,我們很多時候常用一個構(gòu)造方法是GridView.builder(gridDelegate: itemBuilder:),它接收一個delegate對象,并且跟ListView一樣接收一個itemBuilder方法。
SliverGridDelegateWithFixedCrossAxisCount的構(gòu)造方法如下:
SliverGridDelegateWithFixedCrossAxisCount({
@required this.crossAxisCount,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
可以看得出來它是把GridView.count()的幾個參數(shù)封裝了一下,具體的用法和效果跟GridView.count()一樣,這里就不贅述了。
SliverGridDelegateWithFixedCrossAxisCount在很多情況下都能滿足我們的布局需求,但是有一個不足,因為它設置的每一行數(shù)是一個定值。
當我們把屏幕旋轉(zhuǎn),此時原來的高度會變?yōu)楝F(xiàn)在的寬度,效果就會如下:

所以我們可以使用下面delegate來解決這個問題。
SliverGridDelegateWithMaxCrossAxisExtent
我們可以在GridView.builder(gridDelegate: itemBuilder:)方法內(nèi)傳入另外一個參數(shù)SliverGridDelegateWithMaxCrossAxisExtent
構(gòu)造方法如下:
const SliverGridDelegateWithMaxCrossAxisExtent({
@required this.maxCrossAxisExtent,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
})
這里有一個比較重要的參數(shù)就是maxCrossAxisExtent,這個值表示的是子控件最大的寬度是多少。
舉個例子:
手機的屏幕寬度為375,子控件之間的間距為0,maxCrossAxisExtent的值設置為100,那么我們知道子控件的寬度取值區(qū)間在0~100之間。
- 假設我們布局
3個子控件,3乘以最大值100等于300,很明顯是不能滿足布局在375的寬度上的。 - 假設我們布局
4個子控件,4乘以100等于400,400大于375。我們知道寬度的取值區(qū)間在0~100,375 / 4 = 93.75既滿足了寬度小于100,又滿足了可以充滿375的寬度,那么子控件的個數(shù)為4寬度為93.75
這就是maxCrossAxisExtent的用法。
其實GridView還可以做瀑布流效果,感興趣的同學可以去查一下。
想體驗以上的示例的運行效果,可以到我的Github倉庫項目flutter_app->lib->routes->gridview_page.dart查看,并且可以下載下來運行并體驗。