Help us understand the problem. What is going on with this article?

Flutterの基本的なレイアウトの話

More than 1 year has passed since last update.

Flutterアプリを作成するにあたって必要なレイアウトWidgetについて紹介。
レイアウトWidgetで主要になるのは以下のものになる

  • Row
  • Column
  • Center
  • Container

Row

Rowは子要素を横に並べたい場合に使用するWidget
子要素はchildrenに複数のWidgetをArrayとして定義できる。

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Row(
        children: <Widget>[
          Text("item1"),
          Text("item2"),
          Text("item3"),
          Text("item4"),
        ],
      ),
    );
}

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 15.37.29.png

子要素の配置についてmainAxisAlignmentを指定することで制御することができる。

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: <Widget>[
    Text("item1"),
    Text("item2"),
    Text("item3"),
    Text("item4"),
  ],
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 15.37.20.png

mainAxisAlignmentは横の幅に対する設定であるが、縦の位置を設定するcrossAxisAlignmentがあるが、Containerで解説する。

Column

Columnは子要素を縦に並べたい場合に使用するWidget
Row同様子要素はchildrenに複数のWidgetをArrayとして定義できる。

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          Text("item1"),
          Text("item2"),
          Text("item3"),
          Text("item4"),
        ],
      ),
    );
}

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.37.02.png

Row同様子要素の配置についてmainAxisAlignmentを指定することで制御することができる。

Column(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: <Widget>[
    Text("item1"),
    Text("item2"),
    Text("item3"),
    Text("item4"),
  ],
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.38.18.png

ColumnにもcrossAxisAlignmentがある。
ColumnではRowと逆で横の位置を設定できる。

Center

Center Widgetは名の通り子要素の横または縦を真ん中に位置させる為のWidget

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Text('item'),
      ),
    );
  } 

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.46.06.png

ただし、子要素がRowなら縦に対しては真ん中だが横は寄っていたり、Columnなら横に対しては真ん中だが縦が上に寄っていたりするのでmainAxisAlignmentを指定して調整が必要。

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.53.50.png Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.54.01.png

Container

Containerは子のサイズやpadding,marginなどの設定ができる。
わかりやすくするためにContainerの枠に色をつける

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        decoration: BoxDecoration(border: Border.all(
            color: Colors.red,
            width: 8.0,
          ),
        ),
      ),
    );
  }

Containerはサイズを指定しなければ子要素のサイズに依存する

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.41.14.png Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.41.23.png

widthとheightを指定するとこのようになる

Container(
  width: 200.0,
  height: 400.0,
  decoration: BoxDecoration(border: Border.all(
      color: Colors.red,
      width: 8.0,
    ),
  ),
  child: Text('test'),
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.45.35.png

margin,paddingを設定してみる
marginとpaddingを指定するときはEdgeInsetsというWidgetを使用する。
EdgeInsets.allで全方向一定の指定、EdgeInsets.onlyで指定した方向に設定できる。

topにmarginを50.0、leftにpaddingを50.0で指定してみる。

Container(
  width: 200.0,
  height: 400.0,
  padding: EdgeInsets.only(left: 50.0),
  margin: EdgeInsets.only(top:50.0),
  decoration: BoxDecoration(border: Border.all(
      color: Colors.red,
      width: 8.0,
    ),
  ),
  child: Text('test'),
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.50.40.png

このようにmargin,paddingはEdgeinsertsを使用して指定できる。

次にContainerの子要素にColumn,Rowを使ってみる。
Containerの子要素にRowを指定、中心に等間隔で並べてみる。

Container(
  height: 300.0,
  decoration: BoxDecoration(border: Border.all(
      color: Colors.red,
      width: 8.0,
    ),
  ),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
      Text('item1'),
      Text('item2'),
      Text('item3'),
      Text('item4')
    ],
  ),
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.57.37.png

このとき、高さはContainer内の中心に位置しているが、上部や下部に表示したい場合もある。
ここでcrossAxisAlignmentを設定すると上下にも位置を調節できる。

Container(
  height: 300.0,
  decoration: BoxDecoration(border: Border.all(
      color: Colors.red,
      width: 8.0,
    ),
  ),
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.end,
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
      Text('item1'),
      Text('item2'),
      Text('item3'),
      Text('item4')
    ],
  ),
),

Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 18.01.15.png

まとめ

今回紹介した4つはFlutterではかなり使用頻度が高くなる。
特にContainerはサイズ指定やmargin,padding指定ができるため、親に指定することがかなり多くなる。
とりあえずサイズを変えたい、周りに余白が欲しいとなった時はとりあえずContainerを親に指定すればなんとかなる。
ただ、FlutterはWidgetの性質上ネストが深くなることが多いため、最小の組み合わせでレイアウトを組むことを意識したい。

shinbey221
ふろんとえんどえんじにあ。
kaonavi
クラウド人材管理ツール「カオナビ」の製造・販売・サポートを行い、企業の人材管理にイノベーションを起こすことを目的としている会社
https://www.kaonavi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away