彈性布局(Flex)
彈性布局允許子組件按照一定比例來分配父容器空間。彈性布局的概念在其它UI系統中也都存在,如H5中的彈性盒子布局,Android中的FlexboxLayout
等。Flutter中的彈性布局主要通過Flex
和Expanded
來配合實現。
Flex
Flex
組件可以沿着水平或垂直方向排列子組件,如果你知道主軸方向,使用Row
或Column
會方便一些,因為Row
和Column
都繼承自Flex
,參數基本相同,所以能使用Flex的地方基本上都可以使用Row
或Column
。Flex
本身功能是很強大的,它也可以和Expanded
組件配合實現彈性布局。接下來我們只討論Flex
和彈性布局相關的屬性(其它屬性已經在介紹Row
和Column
時介紹過了)。
Flex({ ... @required this.direction, //彈性布局的方向, Row默認為水平方向,Column默認為垂直方向 List<Widget> children = const <Widget>[], })
Flex
繼承自MultiChildRenderObjectWidget
,對應的RenderObject
為RenderFlex
,RenderFlex
中實現了其布局算法。
Expanded
可以按比例“擴伸” Row
、Column
和Flex
子組件所占用的空間。
const Expanded({
int flex = 1,
@required Widget child,
})
flex
參數為彈性系數,如果為0或null
,則child
是沒有彈性的,即不會被擴伸占用的空間。如果大於0,所有的Expanded
按照其flex的比例來分割主軸的全部空閑空間。下面我們看一個例子:
class FlexLayoutTestRoute extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: <Widget>[ //Flex的兩個子widget按1:2來占據水平空間 Flex( direction: Axis.horizontal, children: <Widget>[ Expanded( flex: 1, child: Container( height: 30.0, color: Colors.red, ), ), Expanded( flex: 2, child: Container( height: 30.0, color: Colors.green, ), ), ], ), Padding( padding: const EdgeInsets.only(top: 20.0), child: SizedBox( height: 100.0, //Flex的三個子widget,在垂直方向按2:1:1來占用100像素的空間 child: Flex( direction: Axis.vertical, children: <Widget>[ Expanded( flex: 2, child: Container( height: 30.0, color: Colors.red, ), ), Spacer( flex: 1, ), Expanded( flex: 1, child: Container( height: 30.0, color: Colors.green, ), ), ], ), ), ), ], ); } }
運行效果如圖示:
示例中的Spacer
的功能是占用指定比例的空間,實際上它只是Expanded
的一個包裝類,Spacer
的源碼如下:
class Spacer extends StatelessWidget { const Spacer({Key key, this.flex = 1}) : assert(flex != null), assert(flex > 0), super(key: key); final int flex; @override Widget build(BuildContext context) { return Expanded( flex: flex, child: const SizedBox.shrink(), ); } }
小結
彈性布局比較簡單,唯一需要注意的就是Row
、Column
以及Flex
的關系。