构建一个布局
-
创建一个 widget 容纳可见对象
比如文字
Text('Hello World', style: TextStyle(fontSize: 32.0))
。比如图片
Image.asset('images/myPic.jpg', fit: BoxFit.cover)
。比如 icon
Icon(Icons.star, color: Colors.red[500])
。 -
将上面的 widget 作为一个 child 和 children 添加到布局 widget,这个 widget 提供边距,对齐等功能。
Center( child: Text('Hello World', style: TextStyle(fontSize: 32.0)) )
-
将布局 widget 添加到页面
如果是 Material 的,可用 Scaffold,它提供了一个默认 banner,背景色,并且具有添加 drawer,snack bar 和底部 sheet 的API。
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Text('Hello World', style: TextStyle(fontSize: 32.0)), ), ); } }
如果不用 Material,没有 AppBar,背景色,标题这样,就用一个普通的 Container。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration(color: Colors.white), child: Center( child: Text('Hello World', textDirection: TextDirection.ltr, style: TextStyle(fontSize: 40.0, color: Colors.black87)), ), ); } }
垂直和水平放置多个 widget
使用 Row
水平排列,用 Column
垂直排列。它们都通过 children 添加一个子 widget 列表。
分析上图布局:
- 最外层是一个 Row,有两个 child:第一列是一个 Column,第二列是一个 Image
- 左侧的 Column 有四个 child:第一行和第二行是 Text,第三行和第四行是一个 Row
这样一层一层地分析,复杂 widget 就变成了最基础的 widget。
对齐 widgets
15462348828519.png 15462348950053.png对于 Row,主轴是水平方向,对于 Column,主轴是垂直方向。使用 mainAxisAlignment
和 crossAxisAlignment
属性来对齐它们的子项。
将之前的示例代码中的图像改成
Widget rowImageSection = Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/lake.jpg', width: 100, height: 80,),
Image.asset('images/lake.jpg', width: 100, height: 80,),
Image.asset('images/lake.jpg', width: 100, height: 80,),
],
);
Widget columnImageSection = Container(
height: 300,
color: Colors.blueGrey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/lake.jpg', width: 100, height: 80,),
Image.asset('images/lake.jpg', width: 100, height: 80,),
Image.asset('images/lake.jpg', width: 100, height: 80,),
],
)
);
return MaterialApp(
...
home: Scaffold(
...
body: ListView(
children: [
// Image.asset(
// 'images/lake.jpg',
// width: 600.0,
// height: 240.0,
// fit: BoxFit.cover,
// ),
rowImageSection,
columnImageSection,
titleSection,
buttonSection,
textSection,
],
),
),
);
分别有一行和一列,图片宽 100 px,高 80 px,列的高度是 300 px,大于三张图片高度的和,其中列设置了背景颜色,以便区分。
-
spaceEvenly 前后均匀分配空闲空间
屏幕快照 2018-12-31 下午2.39.07.png -
spaceAround 左右两侧的距离是中间的一半
屏幕快照 2018-12-31 下午2.51.01.png -
spaceBetween 两侧没有距离,只在 child 之间平均分配
屏幕快照 2018-12-31 下午2.52.27.png -
center 居中显示
屏幕快照 2018-12-31 下午2.43.08.png -
start 从开始处排列
屏幕快照 2018-12-31 下午2.44.28.png -
end 排字最后
屏幕快照 2018-12-31 下午2.47.41.png
调整 widget
children: [
Image.asset('images/lake.jpg', width: 200,),
Image.asset('images/lake.jpg', width: 200,),
Image.asset('images/lake.jpg', width: 200,),
]
如果布局太大超出设备尺寸,边缘显示会有问题,如下图
屏幕快照 2018-12-31 下午3.20.36.png可将 Row
或 Column
中的 child 放入 Expanded
,会使得子 widget 自适应。
children: [
new Expanded(
child: Image.asset('images/lake.jpg', width: 200,),
),
new Expanded(
child: Image.asset('images/lake.jpg', width: 200,),
),
new Expanded(
child: Image.asset('images/lake.jpg', width: 200,),
),
],
屏幕快照 2018-12-31 下午3.27.31.png
Expanded widget 有 flex 属性,是一个整数,用于确定 widget 的弹性系数,默认值是 1。
Widget rowImageSection = Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: Image.asset('images/lake.jpg', width: 200,),
),
new Expanded(
flex: 2,
child: Image.asset('images/lake.jpg', width: 200,),
),
new Expanded(
child: Image.asset('images/lake.jpg', width: 200,),
),
],
);
crossAxisAlignment 指定 Row 的垂直方向居中,中间是左右两边的两倍。
屏幕快照 2018-12-31 下午3.29.03.png聚集 widgets
默认情况下,行和列沿着主轴会尽可能占用尽可能多的空间,但如果要将它们聚集在一起,可以将 mainAxisSize 设为 MainAxisSize.min。
var packedRow = Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.black),
Icon(Icons.star, color: Colors.black),
],
);
15462421984413.png
只是即使没有 mainAxisSize: MainAxisSize.min
这一句效果也一样。
网友评论