[toc]
Row、Column
Row 水平方向排放子 Widget, Column 垂直方向排放 children 但不可以滚动,它们都继承自 Flex,借鉴了 web 的中的 Flex 布局。
对于 Row 来说,主轴是水平方向,横轴垂直方向。对于 Column 来说,主轴垂直方向,横轴水平方向。
mainAxisSize 用来设置 Row 或 Column 的大小。
- MainAxisSize.max :类似 match_parent,尽可能的大
- MainAxisSize.min :类似 wrap_content, 尽可能的小
mainAxisAlignment 和 crossAxisAlignment 两个方向上的对齐组合完成 children 的定位,start center end 分别代表左中右。
- MainAxisAlignment.spaceEvenly :平分剩余空间
- MainAxisAlignment.spaceAround : 平分剩余空间,但左右两边只能分到二分之一
- MainAxisAlignment.spaceBetween :平分剩余空间,但左右两边不会分到
textDirection 可以改变 children 的布局顺序,默认 TextDirection.ltr(left to right)。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("RowWidget"),),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,//平分剩余空间
mainAxisSize: MainAxisSize.max,// Row 宽度最大 类似 match_parent
crossAxisAlignment: CrossAxisAlignment.start, // y 轴对齐 top
verticalDirection: VerticalDirection.up, // 如果 crossAxisAlignment 是 start 变为 end
textDirection: TextDirection.rtl, // children 的排列方式 right to left
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.pinkAccent,
),
Container(
width: 100,
height: 100,
color: Colors.lightGreenAccent,
),
Container(
width: 50,
height: 50,
color: Colors.lightGreenAccent,
),
],
),
),
);
}
当 children 超出主轴尺寸时,Row 和 Column 会产生异常。将可以伸缩的内容放到 Expanded 中可以避免这样的异常。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("RowWidget"),),
body: Row(
mainAxisSize: MainAxisSize.max,// Row 宽度最大 类似 match_parent
crossAxisAlignment: CrossAxisAlignment.start, // y 轴对齐 top
verticalDirection: VerticalDirection.up, // 如果 crossAxisAlignment 是 start 变为 end
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.pinkAccent,
),
//两个 Expanded 分剩下的空间 Text 占 1/ 3(两个 Expanded flex 属性的和)
Expanded(
flex: 1,// 比例 默认 1
child: Text("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
),
Expanded(
flex: 2,
child: Container(
width: 100,
height: 100,
color: Colors.lightGreenAccent,
),
)
],
),
),
);
}
Stack
Stack 类似 FrameLayout ,children 一层压一层。
children 分为两种:
- positioned :Positioned Widget 包裹真正的 child ,通过 top、left 属性定位。
- non-positioned :没有被 Positioned Widget 包裹,通过 Stack 的 alignment 定位
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stack'),
),
body: Container(
width: 300,
height: 300,
child: Stack(
alignment: AlignmentDirectional.center,
// fit 只对 non-positioned child 生效
//loose 使用 child 自己的大小约束
//expand 所有 child 使用 Stack 大小约束
//passthrough child 是 Row x轴使用 Stack 大小约束 ,y 轴使用自己的大小约束
fit: StackFit.loose,
overflow: Overflow.visible, // 高度 1000 的 Container 并没有可见,不知道有啥子用
children: <Widget>[
Container(
width: 200,
height: 200,
color: Colors.lightGreenAccent,
),
Container(
width: 100,
height: 1000,
color: Colors.redAccent,
),
Positioned(
left: 80,
top: 20,
child: Container(
width: 50,
height: 50,
color: Colors.pinkAccent,
),
),
Row(
// Row 默认 children 对齐是 start , Stack 的 fit 改成 passthrough 观察 Text 位置
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('AAA'),
],
)
],
),
),
),
);
}
IndexedStack
IndexedStack 每次只显示 Stack 中 index 指定的一层,index 默认为 0。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stack'),
),
body: Container(
width: 300,
height: 300,
child: IndexedStack(
alignment: AlignmentDirectional.center,
//显示 child 索引,默认值为 0
index: 1,
children: <Widget>[
Container(
width: 200,
height: 200,
color: Colors.lightGreenAccent,
),
Container(
width: 100,
height: 1000,
color: Colors.redAccent,
),
],
),
),
),
);
}
网友评论