Flutter 佈局基礎 ——Row 水平佈局#
Flutter 中水平佈局使用Row
,可設定元素水平方向排列,如果想要子元素充滿,可把子元素使用Expanded
包括起來。
背景#
使用Row
佈局的 Widget,不能滑動;通常使用 Row 佈局的時候,默認所有的子元素加起來不能超過父視圖的寬度。如果想要橫向滑動,可考慮使用 ListView。
Ps:當所有子元素的寬度超出了父視圖Row
的寬度後,會有警告。
如果想要豎向佈局,使用Column
。
如果只有一個元素,可考慮使用Align
或者Center
來佈局。
基礎介紹#
- Row 常用屬性
- children: 子視圖
- textDirection: 子視圖佈局方向
- TextDirection.ltr: 從左到右
- TextDirection.rtl: 從右到左
- mainAxisAlignment: 子視圖在父視圖上的佈局方式,水平方向佈局
- MainAxisAlignment.spaceAround: 子視圖之間和子視圖距離父視圖都留有間距
- MainAxisAlignment.center: 所有子試圖居中
- MainAxisAlignment.end: 所有子視圖居最末尾
- MainAxisAlignment.spaceBetween: 子視圖之間留有相等間距,與父視圖不留間距
- MainAxisAlignment.spaceEvenly: 子視圖之間和子視圖距離父視圖都留有間距,且間距都相等
- MainAxisAlignment.start,所有子視圖居於最開始
注意 mainAxisAlignment 在子元素使用了Expanded
時,沒有效果;當所有子元素超出了父視圖的寬度時,也沒有效果。
子元素不使用Expanded
,那麼子元素的寬度是根據內容適應,即內容有多少,寬度就有多少。示例如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Row(
children: [
Text(
'First',
style: TextStyle(backgroundColor: Colors.lightBlueAccent),
textAlign: TextAlign.center,
),
Text('Second',
style: TextStyle(backgroundColor: Colors.lightGreenAccent),
textAlign: TextAlign.center),
Text('Third',
style: TextStyle(backgroundColor: Colors.orangeAccent),
textAlign: TextAlign.center),
],
),
)),
);
}
}
效果如下:
注意,上面的Text
中設定了 textAlign,但是不論設定什麼效果都是一樣的。
如果想要上面的 first、second、third 充滿螢幕的寬度,要怎麼設定呢?很簡單,直接使用Expanded
包括起來即可。示例如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Row(
children: [
Expanded(
child: Text('First left',
style: TextStyle(backgroundColor: Colors.lightBlueAccent),
textAlign: TextAlign.left)),
Expanded(
child: Text('Second center',
style: TextStyle(backgroundColor: Colors.lightGreenAccent),
textAlign: TextAlign.center)),
Expanded(
child: Text('Third right',
style: TextStyle(backgroundColor: Colors.orangeAccent),
textAlign: TextAlign.right)),
],
),
)),
);
}
}
效果如下:
同樣,上面的Text
設定了 textAlign,設定不同的 textAlign,會發現不同的顯示效果,對比後能發現,同時使用Expanded
包括起來後,相當於三個子元素均分了螢幕寬度。
實戰#
來看一個效果,左側一個小 Icon,中間是一段很長的文案,右邊再有一個小 Icon。
現在來對比一下,下面幾種情況的顯示效果:
- 所有子元素都沒有
Expanded
的情況 - 所有子元素都使用
Expanded
的情況 - 中間很長的文案使用
Expanded
,其它子元素不用的情況
所有子元素都沒有Expanded
的情況#
代碼如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Row(children: [
const FlutterLogo(),
const Text(
"Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android."),
const Icon(Icons.sentiment_satisfied),
]),
),
));
}
}
效果如下:
可以看到左側 Icon 顯示出來了,且是原始大小;中間的文案顯示了,但是未完成;右側的 Icon 看不到。
還記得最開始說的當子元素的寬度超出時,Flutter 會顯示提示,圖片中最右側紅框標出來的部分,就是 Flutter 的提示。
所有子元素都使用Expanded
的情況#
代碼如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Row(children: [
Expanded(child: FlutterLogo()),
Expanded(
child: const Text(
"Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.")),
Expanded(child: const Icon(Icons.sentiment_satisfied)),
]),
),
));
}
}
效果如下:
可以看到,所有子元素都顯示出來了,且所有子元素均分了父元素的寬度,從中間文案的顯示可以看出。驗證了之前所說的,當所有子元素都使用Expaned
包括時,會平均分配寬度。
中間很長的文案使用Expanded
,其它子元素不用的情況#
代碼如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Row(children: [
const FlutterLogo(),
Expanded(
child: const Text(
"Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.")),
const Icon(Icons.sentiment_satisfied),
]),
),
));
}
}
效果如下:
可以看出,所有子元素都顯示出來了,且,左側 Icon 和右側 Icon 的大小是按照本身的大小顯示,然後餘下的部分用於顯示了文本,且沒有超出。