PS:長期にわたって続けることは難しいことです。
Flutter は Google が提供するクロスプラットフォーム UI フレームワークで、Android と iOS 上で高品質なアプリケーションを迅速に構築できます。主な特徴は、Flutter が迅速な開発能力、表現力豊かで柔軟な UI、そして優れたネイティブパフォーマンスを持っていることです。本記事では Flutter の Flex レイアウトについて紹介します。以下の内容です:
- Flex の基本
- Flex の一般的な設定
- Row と Column
- Expanded と Flexible
- Spacer
- まとめ
Flex の基本#
Flex レイアウト方式は、フロントエンドやミニプログラム開発で広く使用されています。以前に Flex レイアウトを学んでいれば、Flutter でも大差ありません。Flexible Box の図は以下の通りです:
この図の説明については、前のこの記事を参照してください:
Flex Widget は主軸の方向を設定できます。主軸の方向がわかれば、Row または Column を直接使用できます。Flex Widget はスクロールできません。スクロールが必要な場合は ListView を使用することを検討してください。Flex Widget の内容がその幅と高さを超えると、黄黒の警告ストライプが表示されます。水平方向の例で表示されるエラーメッセージは以下の通りです:
I/flutter (14749): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (14749): The following assertion was thrown during layout:
I/flutter (14749): A RenderFlex overflowed by 440 pixels on the right.
エラーメッセージは以下の通りです:
Flex の一般的な設定#
Flex の一般的な属性は以下の通りです:
- direction
- mainAxisAlignment
- mainAxisSize
- crossAxisAlignment
- verticalDirection
- textBaseline
direction#
主軸の方向を設定します。設定可能な値は Axis.horizontal と Axis.vertical で、交差軸は主軸の方向に対して垂直です。
mainAxisAlignment:#
子 Widget を主軸方向に沿って配置する方法を設定します。デフォルトは MainAxisAlignment.start で、設定可能な方法は以下の通りです:
- MainAxisAlignment.start:左揃え、デフォルト値;
- MainAxisAlignment.end:右揃え;
- MainAxisAlignment.center:中央揃え;
- MainAxisAlignment.spaceBetween:両端揃え;
- MainAxisAlignment.spaceAround:各 Widget の両側の間隔が等しく、画面の端との間隔は他の Widget の間隔の半分;
- MainAxisAlignment.spaceEvenly:各 Widget を均等に分配し、画面の端との間隔が他の Widget の間隔と等しい。
比較効果は以下の通りです:
mainAxisSize#
主軸のサイズを設定します。デフォルトは MainAxisSize.max で、設定可能な値は以下の通りです:
- MainAxisSize.max:主軸のサイズは親コンテナのサイズ;
- MainAxisSize.min:主軸のサイズはその子 Widget のサイズの合計。
比較効果は以下の通りです:
mainAxisAlignment を spaceBetween に設定し、mainAxisSize を max に設定すると、全体の Row の幅に基づいて spaceBetween の方法で配置されます。mainAxisSize を min に設定すると、3 つの Container の幅の合計範囲内で spaceBetween の方法で配置されます。
crossAxisAlignment#
子 Widget を交差軸方向に沿って配置する方法を設定します。デフォルトは CrossAxisAlignment.center で、設定可能な方法は以下の通りです:
- CrossAxisAlignment.start:交差軸の開始位置に揃える;
- CrossAxisAlignment.end:交差軸の終了位置に揃える;
- CrossAxisAlignment.center:中央揃え;
- CrossAxisAlignment.stretch:交差軸全体を埋める;
- CrossAxisAlignment.baseline:最初の行の文字基線に揃える。
比較効果は以下の通りです:
verticalDirection#
垂直方向の子 Widget の配置順序を設定します。デフォルトは VerticalDirection.down で、設定方法は以下の通りです:
- VerticalDirection.down:start が上部、end が下部;
- VerticalDirection.up:start が下部、end が上部。
比較効果は以下の通りです:
交差軸設定の CrossAxisAlignment.end に注意して、これに基づく垂直方向の変化を観察してください。
textBaseline#
文字の揃えの基線タイプを設定します。設定可能な値は以下の通りです:
- TextBaseline.alphabetic:文字基線に揃える;
- TextBaseline.ideographic:表意文字基線に揃える;
使用時に crossAxisAlignment を baseline に設定する場合、textBaseline 属性の値を設定する必要があります。使用方法は以下の通りです:
// textBaseline
class FlexSamplePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flex Sample"),
centerTitle: true,
),
body: Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Text("躬",style: TextStyle(fontSize: 40,),),
Text("x",style: TextStyle(fontSize: 60,),),
Text("ing",style: TextStyle(fontSize: 16,),),
Text("之",style: TextStyle(fontSize: 16,),),
],
)),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text("躬",style: TextStyle(fontSize: 40,),),
Text("x",style: TextStyle(fontSize: 60,),),
Text("ing",style: TextStyle(fontSize: 16,),),
Text("之",style: TextStyle(fontSize: 16, ),),
],
)),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
Text("躬",style: TextStyle(fontSize: 40, ),),
Text("x",style: TextStyle(fontSize: 60,),),
Text("ing",style: TextStyle(fontSize: 16,),),
Text("之",style: TextStyle(fontSize: 16,),),
],
))
],
),
);
}
}
textBaseline 属性を設定しない場合、TextBaseline.alphabetic および TextBaseline.ideographic を設定した場合の比較効果は以下の通りです:
両者は基線の意味において異なりますが、テストでは違いが見られませんでした。今後も観察を続け、知っている方はコメントで指摘してください。
Row と Column#
Row と Column はどちらも Flex を継承しています。Row の主軸の方向は水平方向で、Column の主軸の方向は垂直方向です。つまり、Flex の基本に基づいて主軸の方向を設定します。以下の通りです:
// Row
direction: Axis.horizontal,
/// Column
direction: Axis.vertical,
主軸の方向が確定している場合は、Row または Column を直接使用できます。使用方法は Flex と同じです。
Expanded と Flexible#
Flexible の fix 属性はデフォルトで FlexFit.loose ですが、Expanded は Flexible を継承し、その fix 属性は FlexFit.tight に指定されています。両者は fix 属性が異なるため異なります。Flexible の fit 属性を FlexFit.tight に設定すると、Flexible は Expanded と等価になります。設定可能な fit 属性は以下の通りです:
- tight:利用可能なスペースを強制的に埋める;
- loose:利用可能なスペースを強制的に埋めず、Widget 自身のサイズ。
比較効果は以下の通りです:
Expanded は Row、Column、Flex 内のコンポーネントが主軸の利用可能なスペースを埋めることを可能にします。複数の Widget が Expanded コンポーネントを使用している場合、Expanded の flex 属性を使用して主軸のスペースを比率で分配できます。flex 属性は Android の LinearLayout の weight 属性に相当します。以下の通りです:
// Expanded
class ExpandedSamplePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Row Sample"),
centerTitle: true,
),
body: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
width: 50,
height: 50,
color: Colors.red,
child: Center(
child: Text(
"A",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
),
Expanded(
flex: 2,
child: Container(
width: 50, // Row Expanded下width無効
height: 50, // Column Expanded下height無効
color: Colors.green,
child: Center(
child: Text(
"B",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
),
Container(
width: 50,
height: 50,
color: Colors.yellow,
child: Center(
child: Text(
"C",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
],
));
}
}
表示効果は以下の通りです:
Spacer#
Spacer は Widget 間の間隔を調整するために使用され、すべての残りのスペースを占有します。そのため、MainAxisAlignment の設定は無効になります。Spacer の属性 flex は残りのスペースの配分の重みを設定するために使用され、デフォルト値は 1 で、すべての残りのスペースを占有します。2 つ以上の Spacer がある場合は、flex に従って残りのスペースを配分します。コードは以下の通りです:
class RowSamplePage1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Row Sample"),
centerTitle: true,
),
body: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 150),
child: Row(
children: <Widget>[
Container(
width: 80,
height: 80,
color: Colors.red,
),
Spacer(flex: 1,),
Container(
width: 80,
height: 80,
color: Colors.green,
),
Spacer(flex: 2,),
Container(
width: 80,
height: 80,
color: Colors.yellow,
),
],
),
));
}
}
表示効果は以下の通りです:
以上は Flutter における Flex レイアウトに関する内容を主に学びました。重点は Flex の基本概念を理解し、その上で Flex レイアウトを学び、検証することです。