LoginSignup
29
16

More than 3 years have passed since last update.

FlutterでWidgetを絶対位置で配置してみる(position: absolute; 風に)

Last updated at Posted at 2019-07-14

Flutterで複数のWidgetを配置したいとき、選択肢としてまずColumnやRowが挙げられます。
ColumnやRowでは、Widgetは相対位置で配置されます。つまり、1つ前のWidgetが基準となり、その下にWidgetが追加されます。CSSで言うところのposition: relative; を指定したようなイメージです。

position: absolute;を指定した時のように絶対位置でWidgetを配置したいときは、StackというWidgetと
①Positioned
②Align
これらのWidgetを組み合わせて使うと簡単です。


使い方は以下のように、分かりやすいものとなっています。

①Positionedを使ったとき

main.dart
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が便利です。

main.dart
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に対して任意の位置に配置することが可能です。

29
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
16