flutter.svg

【Flutter】レイアウトの基本

Flutter

Container

Containerは、HTML の<div>のように子ウィジェットを内包し、大きさや位置などを調整するためのものです。

Container(
  alignment: Alignment.center,
  child: Text("はじめてのレイアウト"),
  constraints: BoxConstraints.expand(height: 300),
  decoration: BoxDecoration(
    border: Border.all(color: Colors.blue, width: 5),
    borderRadius: BorderRadius.circular(10),
    boxShadow: [
      BoxShadow(
        color: Colors.black26,
        blurRadius: 3.0,
        spreadRadius: 1.0,
        offset: Offset(5, 5),
      ),
    ],
    color: Colors.blue[50],
  ),
  margin: EdgeInsets.all(10),
  padding: EdgeInsets.all(10),
)

Containerは以下のプロパティを持ちます。

プロパティ説明
alignment子のウィジェットの位置を設定します。
child子のウィジェットを設定します。
color色を設定します。
constraintsコンテンツの大きさの制限を設定する。
decorationデザインを設定する。
heightコンテンツの高さを設定します。
marginmarginを設定します。
paddingpaddingを設定します。
widthコンテンツの幅を設定します。

プロパティについては以下で補足していきます。 Containerについて説明していますが、他のウィジェットのプロパティでも同じ考え方です。

Colors

Colorsは、Flutter で色を設定する際に使用します。 どのような色があるかはこちらを参照してください。

Colors.blue[50]
Colors.red.shade400

Alignment

Alignmentは、ウィジェットの配置位置を指定するのに使用します。 位置は左上を(x, y) = (-1, -1)、右下を(x, y) = (1, 1)の座標で考えることができ、以下のコンストラクタによって設定します。

Alignment(-1, -1)  //左上
Alignment(0, 0)    //中央
Alignment(1, 1)    //右下
Alignment(0.2, -0.6)

また特定の位置は、以下のように定数として用意されています。

定数位置(座標)
topLeft(-1, -1)
topCenter(0, -1)
topRight(1, -1)
centerLeft(-1, 0)
center(0, 0)
centerRight(1, 0)
bottomLeft(-1, 1)
bottomCenter(0, 1)
bottomRight(1, 1)

BoxConstraints

BoxConstraintsは、ウィジェットの大きさに関する設定で使用します。

コンストラクタの引数にminHeightmaxHeightminWidthmaxHeightを指定することで、幅と高さの最大、最小値を設定します。 引数の指定がない場合は、ウィジェットは親と同じ大きさになります。

BoxConstraints(
  minHeight: 200,
  maxHeight: 300,
  minWidth: 150,
  maxWidth: 400,
)
BoxConstraints()  //親と同じサイズ

単純に固定サイズを設定する場合は、BoxConstraints.expandheightwidthを指定します。 指定しなかった場合は、親と同じサイズになります。

BoxConstraints.expand(height: 300, width: 200)
BoxConstraints.expand(height: 300)   //幅は親と同じ
BoxConstraints.expand(width: 200)    //高さは親と同じ

BoxDecoration

BoxDecorationは、枠線や影などのデザインを設定するために使用します。

注意点として、BoxDecorationを使用する際はContainercolorプロパティは設定できません。 代わりにBoxDecorationcolorプロパティを設定します。

Border

Borderによって枠線を設定します。 上下左右それぞれにBorderSideを指定して、色と太さを設定します。

Border(
  top: BorderSide(color: Colors.red, width: 5.0),
  right: BorderSide(color: Colors.blue, width: 1.0),
  bottom: BorderSide(color: Colors.green, width: 3.0),
  left: BorderSide(color: Colors.yellow, width: 10.0)
)

すべて同じデザインの場合は、Border.all()を使用します。

Border.all(color: Colors.red, width: 5.0)

上下(水平方向)、左右(垂直方向)ごとに設定したい場合は、Border.symmetric()を使用します。

Border.symmetric(
  horizontal: BorderSide(color: Colors.red, width: 5.0),
  vertical: BorderSide(color: Colors.blue, width: 1.0),
)

BorderRadius

BorderRadiusは、境界の角を丸めるために使用します。

BorderRadius.circular(10.0)

個別に設定する場合は、BorderRadius.onlyを使用します。 ただし、数値でなくRadiusを指定します。

BorderRadius.only(
  topLeft: Radius.circular(5),
  topRight: Radius.circular(10),
  bottomLeft: Radius.circular(1),
  bottomRight: Radius.circular(20),
)

BoxShadow

BoxShadowは、影を設定するために使用します。

BoxShadow(
  color: Colors.black26,     //影の色
  blurRadius: 10.0,          //ぼかし具合
  spreadRadius: 1.0,         //大きさ
  offset: Offset(5.0, 5.0),  //位置
)

EdgeInsets

EdgeInsetsは、marginpaddingを設定するのに使用します。 使用するコンストラクタによってどのように設定するかが異なります。

EdgeInsets.all(10.0) //全方向同じ値
EdgeInsets.fromLTRB(10.0, 5.0, 2.5, 7.5) //全方向個別指定(左上右下)
EdgeInsets.only( //位置指定
  bottom: 10.0,
  right: 10.0,
)
EdgeInsets.symmetric( //縦横ごとに指定
  vertical: 10.0,
  horizontal: 20.0,
)

SizedBox

SizedBoxは、指定したサイズのスペースを確保するために使用します。

SizedBox(
  child: Text("はじめてのレイアウト"),
  height: 200,
  width: 300,
)

FractionallySizedBox

SizeBoxは固定値でしたが、FractionallySizeBoxを使用すると親ウィジェットに対する割合でサイズを指定することができます。

FractionallySizedBox(
  child: Text("はじめてのレイアウト"),
  heightFactor: 0.7,  //70%
  widthFactor: 0.4,  //40%
)

Align

Alignは、Alignの親ウィジェットを基準に、子ウィジェットの位置を指定します。

Align(
  alignment: Alignment.center,
  child: Text("はじめてのレイアウト"),
)

Center

Centerは、Centerの親ウィジェットの中央になるように子ウィジェット配置します。

Center(
  child: Text("はじめてのレイアウト"),
)

FractionalTranslation

FractionalTranslationは、Offsetを使ってウィジェットの位置を設定します。

FractionalTranslation(
  child: Text("はじめてのレイアウト"),
  translation: Offset(10.0, 5.0),
)

Padding

Paddingは、余白を設定するためのウィジェットです。

Padding(
  child: Text("はじめてのレイアウト"),
  padding: EdgeInsets.all(10.0)
)

Row

Rowは、水平方向にウィジェットを並べるために使用します。 HTML でいうところの Flexbox に近いです。

Row(
  children: <Widget>[
    Container(
      color: Colors.blue,
      height: 100,
      width: 100,
    ),
    Container(
      color: Colors.red,
      height: 50,
      width: 100,
    ),
    Container(
      color: Colors.green,
      height: 150,
      width: 100,
    )
  ],
  mainAxisAlignment: MainAxisAligment.start,
  crossAxisAlignment: CrossAxisAlignment.center
)

ウィジェットの並べ方については以下より説明します。

MainAxisAlignment

水平方向の位置を設定します。

MainAxisAlignment.start
MainAxisAlignment.center
MainAxisAlignment.end
MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceAround
MainAxisAlignment.spaceEvenly

start

1
2
3

center

1
2
3

end

1
2
3

spaceBetween

1
2
3

spaceAround

1
2
3

spaceEvenly

1
2
3

CrossAxisAlignment

垂直方向の位置を設定します。

CrossAxisAlignment.start
CrossAxisAlignment.center
CrossAxisAlignment.end
CrossAxisAlignment.stretch
CrossAxisAlignment.baseline

start

1
2
3

center

1
2
3

end

1
2
3

stretch

1
2
3

baseline

1
2
3

Expanded

子ウィジェットをExpandedで内包することにより、Rowが幅いっぱい広がるように子ウィジェットの幅を設定します。 具体的には、flexプロパティを指定することにより、幅の比率を指定します。

以下の例であれば、2 つ目の要素(赤)を固定幅としており、残りの幅で 1 つ目の要素(青)と 3 つ目の要素(緑)が 1:2 となるように幅が設定されます。

Row(
  children: <Widget>[
    Expanded(
      flex: 1,
      child: Container(
        color: Colors.blue,
        height: 100,
      ),
    ),
    Container(
      color: Colors.red,
      height: 100,
      width: 100,
    ),
    Expanded(
      flex: 2,
      child: Container(
        color: Colors.blue,
        height: 100,
      ),
    ),
  ],
)

Column

Columnは、垂直方向にウィジェットを並べるために使用します。

Column(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: <Widget>[
    Container(
      color: Colors.blue,
      height: 100,
    ),
    Container(
      color: Colors.red,
      height: 100,
      width: 100,
    ),
    Container(
      color: Colors.green,
      height: 100,
    ),
  ],
)

垂直方向になるだけで、考え方はRowと同じです。

MainAxisAlignmentCrossAxisAligmentはそれぞれ方向が逆になります。 MainAxis とあるように、MainAxisAlignmentは主方向の配置に関するプロパティです。 よってColumnでは垂直方向の配置に関するプロパティとなります。 CrossAxisAlignmentは直行する方向のプロパティのため、Columnでは水平方向のプロパティとなります。

Expandedも同じように使用できます。

Stack

Stackは、子のウィジェットを重ねる場合に使用します。 alignmentプロパティにより、子ウィジェットの位置を調整できます。

Stack(
  alignment: Alignment.center,
  children: <Widget>[
    Container(
      width: 300,
      height: 300,
      color: Colors.blue,
    ),
    Container(
      width: 200,
      height: 200,
      color: Colors.red,
    ),
    Container(
      width: 100,
      height: 100,
      color: Colors.green,
    ),
  ],
)

Positioned

Positionedは、Stackの子ウィジェットの位置と大きさを設定するために使用します。 指定するプロパティは、位置を表すtoprightbottomleft、大きさを表すheightwidthです。

Stack(
  children: <Widget>[
    Container(
      width: 300,
      height: 300,
      color: Colors.blue,
    ),
    Positioned(
      child: Container(
        color: Colors.red,
      ),
      left: 30,
      top: 10,
      height: 200,
      width: 200,
    ),
    Positioned(
      child: Container(
        color: Colors.green,
      ),
      right: 20,
      bottom: 10,
      height: 100,
      width: 100,
    ),
  ],
),

GridView

GridViewは、グリッドレイアウトを行う際に使用します。 RowColumnを組み合わせることでもできますが、1 つのウィジェットで済むためこちらのほうがよい場合もあります。

GridVieは以下のcountetendedを使って設定することが多いです。

count

countでは、列数を指定してグリッドレイアウトを設定します。

GridView.count(
  crossAxisCount: 2,
  mainAxisSpacing: 10.0,
  crossAxisSpacing: 5.0,
  padding: EdgeInsets.all(10.0),
  children: <Widget>[
    Container(
      child: Text("One"),
      color: Colors.blue[50],
    ),
    Container(
      child: Text("Two"),
      color: Colors.red[50],
    ),
    Container(
      child: Text("Three"),
      color: Colors.green[50],
    ),
    Container(
      child: Text("Four"),
      color: Colors.yellow[50],
    ),
    Container(
      child: Text("Five"),
      color: Colors.purple[50],
    ),
  ],
),

列数はcrossAxisCountによって設定します。  設定した列数になるように幅と高さが調整されます。 高さは幅と同じ大きさになるように設定されます。 また、子ウィジェットで大きさを設定しても、グリッドの大きさが優先されます。

mainAxisSpacingcrossAxisSpacingは、要素間のスペースを設定するためのプロパティです。 mainAxisSpacingは行間、crossAxisSpacingは列間のスペースを設定します。

extent

extentでは、列数ではなく子要素の最大幅を設定します。

GridView.extent(
  maxCrossAxisExtent: 150,
  mainAxisSpacing: 10.0,
  crossAxisSpacing: 5.0,
  padding: EdgeInsets.all(10.0),
  scrollDirection: Axis.vertical,
  children: <Widget>[
    Container(
      child: Text("One"),
      color: Colors.blue[50],
    ),
    Container(
      child: Text("Two"),
      color: Colors.red[50],
    ),
    Container(
      child: Text("Three"),
      color: Colors.green[50],
    ),
    Container(
      child: Text("Four"),
      color: Colors.yellow[50],
    ),
    Container(
      child: Text("Five"),
      color: Colors.purple[50],
    ),
  ],
)

最大幅はmaxCrossAxisExtentによって設定します。

countでは列数が固定でしたが、extentではすべての要素が設定した最大幅内におさまるように幅が調整されます。 そのため、extentでは親の大きさによって列数が変化します。

その他のプロパティについてはcountと同じです。