Flutterで複数のWidgetを配置したいとき、選択肢としてまずColumnやRowが挙げられます。
ColumnやRowでは、Widgetは相対位置で配置されます。つまり、1つ前のWidgetが基準となり、その下にWidgetが追加されます。CSSで言うところのposition: relative;
を指定したようなイメージです。
position: absolute;
を指定した時のように絶対位置でWidgetを配置したいときは、StackというWidgetと
①Positioned
②Align
これらのWidgetを組み合わせて使うと簡単です。
使い方は以下のように、分かりやすいものとなっています。
①Positionedを使ったとき
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
// Positionedで配置
WidgetA(),
Positioned(
top: 10.0,
left: 10.0,
width: 100.0,
height: 100.0,
child: WidgetB(),
),
Positioned(
top: 10.0,
right: 10.0,
width: 100.0,
height: 100.0,
child: WidgetC(),
),
Positioned(
bottom: 10.0,
right: 10.0,
width: 100.0,
height: 100.0,
child: WidgetD(),
),
Positioned(
bottom: 10.0,
left: 10.0,
width: 100.0,
height: 100.0,
child: WidgetE(),
),
],
fit: StackFit.expand,
),
);
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment(0.0, 0.0),
color: Colors.white70,
child: Text('Widget A'),
);
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment(0.0, 0.0),
color: Colors.lightGreen,
child: Text('Widget B'),
);
}
}
// 以下同様に、WidgetC, WidgetD, WidgetE
このように、Stackを親Widgetとして、絶対位置で配置することができます。
子Widgetに幅や高さが指定されていない場合は、top, bottom, heightから2つ、left, right, widthから2つの値を指定して、サイズを持たせるようにしましょう。
(この場合は、親WidgetにPaddingをつけるやり方が良いですね....)
②Alignを使ったとき
端に余白をつける必要がなく、Widgetが幅・高さを持っているときには、Alignが便利です。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
// Alignで配置
WidgetA(),
Align(
alignment: Alignment.topLeft,
child: WidgetB(),
),
Align(
alignment: Alignment.topRight,
child: WidgetC(),
),
Align(
alignment: Alignment.bottomRight,
child: WidgetD(),
),
Align(
alignment: Alignment.bottomLeft,
child: WidgetE(),
),
],
fit: StackFit.expand,
),
);
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment(0.0, 0.0),
color: Colors.white70,
child: Text('Widget A'),
);
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
width: 100.0,
height: 100.0,
child: Container(
alignment: Alignment(0.0, 0.0),
color: Colors.lightGreen,
child: Text('Widget B'),
),
);
}
}
// 以下同様に、WidgetC, WidgetD, WidgetE
以下のように、親Widgetに対して任意の位置に配置することが可能です。