Flutter レイアウトの基本 ——Row 水平方向のレイアウト#
Flutter での水平方向のレイアウトにはRow
を使用し、要素を水平方向に配置できます。子要素をいっぱいにしたい場合は、子要素をExpanded
で囲むことができます。
背景#
Row
レイアウトを使用する Widget は、スクロールできません。通常、Row レイアウトを使用する際、すべての子要素の合計幅は親ビューの幅を超えてはいけません。横にスクロールしたい場合は、ListView の使用を検討してください。
Ps:すべての子要素の幅が親ビューのRow
の幅を超えると、警告が表示されます。
縦方向のレイアウトが必要な場合は、Column
を使用します。
要素が 1 つだけの場合は、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
で囲むことで、3 つの子要素が画面の幅を均等に分け合ったことがわかります。
実践#
左側に小さなアイコン、中間に長い文書、右側にもう一つ小さなアイコンを表示する効果を見てみましょう。
以下のいくつかの状況の表示効果を比較します:
- すべての子要素が
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のホットリロードは、迅速かつ簡単に実験、UIの構築、機能の追加、バグの修正を行うのに役立ちます。エミュレーター、シミュレーター、iOSおよびAndroidのハードウェアで、状態を失うことなく、サブ秒のリロード時間を体験できます。"),
const Icon(Icons.sentiment_satisfied),
]),
),
));
}
}
効果は以下の通りです:

左側のアイコンが表示され、元のサイズのままです。中央の文書は表示されていますが、完了していません。右側のアイコンは見えません。
最初に言ったように、子要素の幅が超えた場合、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のホットリロードは、迅速かつ簡単に実験、UIの構築、機能の追加、バグの修正を行うのに役立ちます。エミュレーター、シミュレーター、iOSおよびAndroidのハードウェアで、状態を失うことなく、サブ秒のリロード時間を体験できます。")),
Expanded(child: const Icon(Icons.sentiment_satisfied)),
]),
),
));
}
}
効果は以下の通りです:

すべての子要素が表示され、すべての子要素が親要素の幅を均等に分け合っていることがわかります。中央の文書の表示から確認できます。すべての子要素がExpanded
で囲まれている場合、幅が均等に分配されることが確認されました。
中間の長い文書が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のホットリロードは、迅速かつ簡単に実験、UIの構築、機能の追加、バグの修正を行うのに役立ちます。エミュレーター、シミュレーター、iOSおよびAndroidのハードウェアで、状態を失うことなく、サブ秒のリロード時間を体験できます。")),
const Icon(Icons.sentiment_satisfied),
]),
),
));
}
}
効果は以下の通りです:

すべての子要素が表示され、左側のアイコンと右側のアイコンのサイズはそれぞれのサイズで表示され、残りの部分がテキストの表示に使用され、超過することはありません。