8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Flutter】比率によるレイアウトを学ぶ

Last updated at Posted at 2022-11-29

初めに

Flutterで比率によるレイアウトをするにあたって躓いた部分を記事にしたいと思います。
今回は、Column Rowのプロパティでレイアウトする方法と、FlexibleWidget系のflexを指定してレイアウトする方法をご紹介します。
そんなの余裕だよ!って方は、飛ばして実践編に取り組んでみてください!

Tips

レイアウトを考えるときには、Dart DevToolsFlutter inspector が超便利です!
Tree構造や、余白、Widgetの範囲まで可視化してくれます!

Android Studio
Visual Studio Code

以下で画面に青線や、黄色線が表示されていますが、Flutter Inspectorによるものです。
不具合により、Flutter Inspectorを使えなかったり、上記のステップを飛ばした方はご注意ください。

今回は、比率をわかりやすくしたいので、RowではなくColumnでサンプルを作っていきます。(この記事で伝えたいことは、Rowにもそのまま適用できます)

全てのColumnCenterで囲っています。

復習編

初めは、シンプルにColumnで囲う

当たり前ですが、上から順番に詰めていますね。

mainAxisAlignmentプロパティを指定

childrenの要素数に応じて、Widget間の余白を計算してくれます!

spaceAround spaceBetween spaceEvenly

Expandedで囲う

Expandedは、子要素を描画領域の最大サイズまで引き伸ばす、もしくは縮小させる Widget です。

ただし、Expandedで囲っただけでは、Buttonのタップ可能範囲も引き伸ばされてしまうので、Centerで囲ってあげましょう。
これで、ColumnmainAxisAlignment.spaceAroundを指定した場合と同じレイアウトになりましたね。

Expanded -> child Expanded -> Center -> child

実践編

それでは、以下の仕様を満たしてレイアウトしてみましょう!

  • Icon(Icons.flutter_dash_outlined)Textの間は、50 logical pixel
  • アイコンのサイズは100
  • Icon(Icons.flutter_dash_outlined)Textを合わせた矩形(以下矩形Widget)の垂直中央は画面の中央と同じ
  • TextIcon(Icons.sentiment_satisfied)の間は、100 logical pixel
ヒント

SpacerExpandedを組み合わせてみよう!

解答例

class ColumnWithExpandedAndSpacer extends StatelessWidget {
  const ColumnWithExpandedAndSpacer({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Spacer(
          // 1の場合は省略可能
          flex: 1,
        ),
        Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const [
              Icon(
                Icons.flutter_dash_outlined,
                size: 100,
              ),
              SizedBox(
                height: 50,
              ),
              Text('I love Flutter'),
            ],
          ),
        ),
        Expanded(
          // 1の場合は省略可能
          flex: 1,
          child: Column(
            children: [
              const SizedBox(
                height: 100,
              ),
              Center(
                child: IconButton(
                  onPressed: () {
                    print('Tapped satisfied');
                  },
                  icon: const Icon(Icons.sentiment_satisfied),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

考え方

矩形Widgetを中心に設置する ということを意識すぎると沼にハマってしまうかもしれません。実際に自分も詰まったことがあります。

少し見方を変えると、矩形Widgetの上下のスペースが同じであればよい と考えることができそうですね!

そこで登場するのが、Spacerです!SpacerExpandedと同じように、空いているスペースを描画領域の最大サイズまで引き伸ばしてくれます。
両方、flexというプロパティを保持しており、スペースの割合を指定することができます。
今回は明示的にflex:1としていますが、デフォルトで1が指定されるので省略可能です。

正確にいうと、Expandedが継承しているFlexibleでflexは設定されています。

Expanded
class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// so that the child fills the available space along the flex widget's
  /// main axis.
  const Expanded({
    super.key,
    super.flex,
    required super.child,
  }) : super(fit: FlexFit.tight);
}

class Flexible extends ParentDataWidget<FlexParentData> {
  /// Creates a widget that controls how a child of a [Row], [Column], or [Flex]
  /// flexes.
  const Flexible({
    super.key,
    this.flex = 1,
    this.fit = FlexFit.loose,
    required super.child,
  });
    :
    省略
    :
}


試しにSpacerのflexに2を指定してみましょう。

Column(
  children: [
    const Spacer(
      // flex を指定!
      flex: 2,
    ),
    Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const [
              Icon(
                Icons.flutter_dash_outlined,
                size: 100,
              ),
              SizedBox(
                height: 50,
              ),
              Text('I love Flutter'),
            ],
          ),
    Expanded(child: child),
  ],
),

Spacer : Expanded  =  2 : 1 になっていますね!!

最後に

今回は 比率によるレイアウトのサンプルをご紹介しました!
レスポンシブなデザインに対応するには、比率によるレイアウトを考えることは必須になってきます。

自分もまだまだ勉強中ですので、自由自在にデザインできるように皆さん一緒に頑張りましょう!

参考

Flutter: MainAxisAlignmentを理解する
Flexible と Expanded って何が違うんだっけ?

8
3
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
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?