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


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

- Row
- Column
- Center
- Container

# Row

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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/8cf8133a-15f4-425f-c9ef-0fec5c7516e0.png)


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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/45c1f18b-8610-1f0f-045b-af19a4ed2182.png)


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

# Column

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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/9fac4d31-476d-956d-55ce-277bce7ad763.png)


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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/96789b63-58b2-21bb-f1ff-5a506a59087d.png)


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


# Center

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

```dart
@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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/e74c7ccc-860f-32b5-ea3d-04a45614651c.png)


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

![Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.53.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/5f055006-3661-d8c6-728f-7b19dc363d55.png) ![Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 16.54.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/4b5cbfdd-8f65-414b-f393-15ba3c04c9f5.png)




# Container

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

```dart
  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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/afd671fc-781b-2788-5f86-30c2fa1943e8.png) ![Simulator Screen Shot - iPhone Xʀ - 2019-07-05 at 17.41.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/c0da8114-0559-3d73-0f92-d2ce7c91b93d.png)


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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/e64af2c3-af90-a2c6-b96c-69333624d4f4.png)

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

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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/b2ad287c-07f7-aca4-cae1-d41820267d47.png)


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


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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/92f03588-a362-c93f-2f43-2a0b32a3a7a8.png)



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

```dart
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442896/c27361f9-f942-3dab-8b8f-9a0858dfbb20.png)



# まとめ

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