【Flutter】Widgetの間隔を調整するには

Flutter

前回の【Flutter】ボタンでテキストを変化させるを解説した際に、テキストを表示させているWidgetとボタンのWidgetの配置の間隔を少し開けたいなっておもたのですが、Columnの均等配置を使ったり、Widgetの間にContainerを配置するなどすれば間隔を調整出来るのでしょうが、今ひとつ自由度が低く感じます。例えばWidgetのプロパティで設定出来たりすれば一番良いのですが、そういったプロパティも見当たらず。色々調べた結果、Widgetの間隔を調整する為のWidgetがありましたのでそちらについて調べて行きたいと思います。


Spacer Widget

このSpacer Widgetを使うことで、イメージ的にはandroidstudioのXMLをConstrainLayoutでアイテムの位置関係を調整するような感覚で配置する事が出来ます。

【androidstudio】XMLを触ってみる。

例えば、前回の記事【Flutter】ボタンでテキストを変化させる。でテキストとボタンの間に間隔を開けたい場合にボタンの前後にSpacerを配置する事で前後に均等は間隔を開けることが出来ます。

まずは何も設定していない状態がこちらですね

次にSpacerを配置します。

配置方法は簡単です。指定のWidgetの前後にSpacer(),を配置するだけです。

@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Container(
              width: double.infinity,
              height: 100,
              decoration: BoxDecoration(
                border: Border.all(color: Colors.green, width: 4),
                borderRadius: BorderRadius.circular(20),
              ),
              margin: const EdgeInsets.all(10),
              child: Center(
                  child: Text(
                hello,
                style: const TextStyle(fontSize: 36),
              )),
            ),
            const Spacer(),
            Center(
              child: TextButton(
                style: TextButton.styleFrom(
                  padding: const EdgeInsets.all(16.0),
                  primary: Colors.black,
                  backgroundColor: Colors.blue,
                  textStyle: const TextStyle(fontSize: 20),
                ),
                onPressed: () {
                  helloD();
                },
                child: const Text('Dart'),
              ),
            ),
            const Spacer(),
          ],
        )
        );
  }
}

実際にSpacerを配置してエミュレーターを起動するとこの様になります。

Spacer Widgetを上下に配置しましたが、上にだけ配置した場合は下の画像の様になります。

画面下にボタンが移動しました。ナビゲーションバーに埋没してしまっています。埋没の解消はこちらの記事を参考にして下さい。

・【Flutter】全画面表示にする

一旦より分かりやすくする為にプロジェクトを新しく作って続きを進めて行こうと思います。

まずはこの様にWidgetを配置しました。

構成としては、Rowの中にContainerを3つ横並びにし、containerの中にはColmunで更に3つのContainerを縦並びにして、3色の正方形を並べ、縦横ともに均等配置しました。

例えば、Columnの間隔は’spaceEvenly‘に揃えてありますので、3列をそれぞれを違う値に変えてみます。

それぞれの隙間の間隔を見ていくと、spaceEvenlyでは全ての間隔は同じ間隔となっていて、spaceAroundではそれぞれのWidgetが両端に同じ余白を持っています。spaceBetweenでは初めと最後に余白を持たずWidget同士同じ間隔を持っています。

等間隔で間隔を持ちたい場合にはこの3つを使い分ければいいわけです。

間隔に変化を与えたい場合にSpacer Widgetを使います。

Spacer WidgetはWidgetの間に配置する事でその間の隙間を埋める機能を持っています。戻り値を設定する事がでSpacer同士の対比を設定することも出来ます。

戻り値を指定する場合には

Spacer(flex: 2),

この様に(flex : 2)の様に指定します。戻り値を指定しない場合はこの数値が1として扱われるのですが、Widget間に配置されているSpacerの対比として指定します。

この様に各Wedget間にSpacerを配置して、必要であればFrexに値を設定します。

一番左では2:1の隙間ですし、一番右は1:1:2、中央はSpacerを配置していない部分は隙間がなくなることとなります。


SizedBox

次に扱うのは’SizedBox‘と言うWidgetです。

SizedBoxは戻り値に指定のサイズを入力するだけなので、扱い方が非常に簡単です。こちらの方が直感的には扱いやすいのでは無いかと思います。

SizedBoxは戻り値と言うよりプロパティを設定するような感じです。例えば今回の場合であれば高さを指定することができれば良い訳ですので

                SizedBox(
                    height: 100,
                  ),

この様に指定してやれば、Widget間の間隔を100開けることが出来ます。

当然横幅を調整したい場合には”Width”を指定することになります。

Spacerは隙間を埋める機能があり実装後は隙間がなくなっている状態mainAxisAlignmentでの間隔を指定することが出来なくなったしまいますが、SizedBoxであれば併用することが可能です。

ただ併用するSizedBoxのメリットとも感じた分かりやすさが損なわれる気がします。その辺はお好みですね。

折角名ので左側の間隔をSizedBoxで指定し、更に横の間隔にもSizedBoxを仕込んで見ました。

Padding

次に”Padding”というWidgetについて解説します。

Paddingと言えばWidgetのプロパティの設定で指定するものと思っていましたが、PaddingというWidgetもあるようです。

基本的にはPaddingと言う親要素にて間隔を指定して子要素の周囲に指定の空間を作成すると言った物になります。

まずはTextFieldをアウトラインで囲んでラベルでヒントを設定した状態でTextFieldを選択するとこの様になります。

TextFieldをPaddingの中に入れて間隔を設定する為に以下の様に記述します。

        body: Padding(
          padding: EdgeInsets.all(10),
          child: TextField(
            decoration: InputDecoration(
              labelText: '入力する',
              border: OutlineInputBorder(),
            ),          
          ),
        )


すると以下のようになります。

若干間隔が出来ているのがわかりますね。

2行目でPaddingを指定しているのですが、この値を変化させる事で間隔を変化させる事が出来ます。

縦横の変化をさせたい場合には

padding: EdgeInsets.symmetric(vertical: 10,horizontal: 20),

この様に記述することも出来ます。

まとめ

この様に、Widget間の間隔を調整する方法について調べて見ました。使いどころはそれぞれあると思いますが、うまいこと使い分けて行けると良いですね。しかし、最後の最後で気がついたのですが、SizedBoxとContainerの違いがよくわかりませんね。初めはContainerで間隔取るのは面倒に感じていましたが、結局は一緒な様な。そして結局Paddingが一番自然に感じました。

かなり脳内で進めてしまっているので、最終的なソースコードを貼り付けておきます。

コメントアウト部分など適時操作してみて下さい。

//import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Space Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const SpacerTest(title: 'Space Test'),
    );
  }
}

class SpacerTest extends StatefulWidget {
  const SpacerTest({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<SpacerTest> createState() => _SpacerTestState();
}

class _SpacerTestState extends State<SpacerTest> {
  final int ch = 100;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Container(
              height: double.infinity,
              width: 100,
              child: Column(
                //mainAxisAlignment: MainAxisAlignment.spaceAround,
                //mainAxisAlignment: MainAxisAlignment.spaceBetween,
                //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.blue,
                  ),
                  //Spacer(flex: 2),
                  SizedBox(
                    height: 100,
                  ),

                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.red,
                  ),
                  //Spacer(flex: 1),
                  SizedBox(
                    height: 200,
                  ),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.yellow,
                  ),
                ],
              ),
            ),
            Container(
              width: 50,
            ),
            Container(
              height: double.infinity,
              width: 100,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                //mainAxisAli gnment: MainAxisAlignment.spaceBetween,
                //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  //Spacer(),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.blue,
                  ),
                  //Spacer(),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.red,
                  ),
                  //Spacer(),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.yellow,
                  ),
                ],
              ),
            ),
            Container(
              height: double.infinity,
              width: 100,
              child: Column(
                //mainAxisAlignment: MainAxisAlignment.spaceAround,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  //Spacer(),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.blue,
                  ),
                  //Spacer(),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.red,
                  ),
                  //Spacer(flex: 2),
                  Container(
                    height: 100,
                    width: 100,
                    color: Colors.yellow,
                  ),
                ],
              ),
            )
          ],
        ));
  }
}

コメント