彈性布局(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的關系。
