前言
上一篇介紹了多元素組件:ListView,Scaffold,AppBar,Row,Column,這一節將接着上一篇博文,介紹GridView,CustomScrollView,Flex,以及Wrap多元素組件(下圖爲CustomScrollView實現效果)
GridView
首先,就是GridView,它和ListView相似,只不過表現形式爲網格形式,可以把它看成Android的LayoutManager。如果GridView組件掌握的很好,那麼App界面也是會非常好看,給人賞心悅目。不過需要注意的是,GridView中的gridDelegate屬性,其類型是SliverGridDelegate,是一個抽象類,通過該類可以控制GridView的排列顯示方式,我們先來看看官方文檔的使用方式:
body: GridView.count(
primary: false,
padding: const EdgeInsets.all(20.0),
crossAxisSpacing: 10.0,
crossAxisCount: 2,
children: <Widget>[
const Text("11111111111111111111"),
const Text("22222222222222222222"),
const Text("33333333333333333333"),
const Text("44444444444444444444"),
const Text("55555555555555555555"),
const Text("66666666666666666666"),
],
),
這裏我們沒有看到代碼中使用SliverGridDelegate,那麼它在哪裏呢?其實,在GridView.count中的構造函數裏已經傳入了默認的gridDelegate,通過開發工具我們進入它的源碼:
gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: mainAxisSpacing,
crossAxisSpacing: crossAxisSpacing,
childAspectRatio: childAspectRatio,
),
源碼裏已經使用了SliverGridDelegateWithFixedCrossAxisCount。它有四個屬性,我們先來看看他們的定義:
屬性 | 取值 |
---|---|
crossAxisCount | 橫向軸子元素的數量 |
mainAxisSpacing | 橫向軸之間的間距 |
crossAxisSpacing | 子元素之間的間距 |
childAspectRatio | 子元素的寬高比,比如2.0就表示寬度是高度的2倍 |
gridDelegate還支持SliverGridDelegateWithMaxCrossAxisExtent,同時GridView也和ListView一樣支持GridView.builder來創建,使用代碼與ListView差不多,這裏就不在贅述了,上面代碼實現效果如下:
CustomScrollView
在實際應用裏,佈局情況並不是非此即彼,一般一個界面不會只有一個滾動列表組件,很可能還有別的組件,這個時候CustomScrollView就有用處了,它的使用代碼如下:
return CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: true,//標題欄是否固定
expandedHeight: 250.0,//合併的高度,默認是狀態欄的高度加AppBar的高度
flexibleSpace: FlexibleSpaceBar(
title: Text("我的標題"),
),
),
SliverGrid(
delegate: SliverChildBuilderDelegate((BuildContext context,int index){
return Container(
alignment: Alignment.center,
color: Colors.teal[100*(index%9)],
child: Text("第$index個"),
);
},childCount: 20),
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,//單個子Widget的水平最大寬度
mainAxisSpacing: 10.0,//水平單個子Widget之間間距
crossAxisSpacing: 10.0,//垂直單個子Widget之間間距
childAspectRatio: 4.0,//寬高比
)
),
SliverFixedExtentList(
itemExtent: 50.0,
delegate: SliverChildBuilderDelegate((BuildContext context,int index){
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100*(index%9)],
child: Text("第$index個"),
);
}),
),
],
);
這段代碼看起來非常複雜其實很好理解,在Scaffold中,Appbar等價於SliverAppBar,剛講解的GridView等價於SliverGrid,而ListView等價於SliverFixedExtentList,所以這是一個包含了二個滑動組件的一個佈局容器,其他的代碼中有註釋,這裏就不贅述了。(顯示效果如博文首圖)
特別注意:轉換後的組件都是以“Sliver”開頭的,其本身是不具備滾動特性的,但是放在CustomScrollView中之後,則可以實現滾動的功能。
Flex
Flex英文意思是屈伸,活動,在Flutter裏面也就是彈性佈局,該佈局借鑑了前端裏的Flex佈局方式。用法也十分簡單,我們可以在Flex中傳入一些參數,其具體屬性如下表:
屬性 | 取值 |
---|---|
direction | Axis.vertical表示垂直方向,Axis.horizontal表示水平方向 |
flex | 彈性係數,大於0會按比例來分割,等於0不會擴展佔用的空間 |
可以把它理解爲android:layout_weight屬性,使用代碼如下:
return Scaffold(
appBar: AppBar(title: Text("Flex佈局玩法"),),
body: Column(
children: <Widget>[
Container(
height: 400.0,
child: Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
color: Colors.red,
),
),
Expanded(
flex: 2,
child: Container(
color: Colors.yellow,
),
),
],
),
),
Container(
height: 120.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
color: Colors.blueAccent,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.red,
),
),
],
),
),
],
),
);
上面的例子中,我們實現了Flex佈局。這種佈局還有一種方式,它通過在Row組件裏設置兩邊對齊也可以實現,代碼顯示效果如下:
Wrap
Wrap英文字面是包裹的意思,在前端開發中,我們通常把具有相同的佈局整合在一個大的佈局組件之內,比如說前面一節使用Row去包裹一些組件,因爲它是多子元素組件,但是Row有時候會出問題,比如實際子組件超過屏幕,在這種情況下,我們就需要使用Wrap去代替Row組件,使用代碼如下:
return Scaffold(
appBar: AppBar(title: Text("Wrap組件玩法"),),
body: Wrap(
spacing: 4.0,
runSpacing: 4.0,
children: <Widget>[
Container(
color: Colors.yellow,
child: Text("Python編程指南",style: new TextStyle(color: Colors.lightBlue),),
),
Container(
color: Colors.yellow,
child: Text("Android編程指南",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("Flutter",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("VUE",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("Scaffold",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("Container",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("Colors",style: new TextStyle(color: Colors.lightBlue),)
),
Container(
color: Colors.yellow,
child: Text("Colors.yellow",style: new TextStyle(color: Colors.lightBlue),)
),
],
),
);
其實就是自適應控件佈局容器,當一行放不下的時候會自動換行顯示,這在Java開發中並沒有配套的控件,需要自定義View,而Flutter開發中,直接提供了該組件,實現效果如下:
多子元素組件到這裏就全部講解完成,下一篇博文將介紹Flutter狀態管理。