世界最大級のオンライン学習サービス「Udemy(ユーデミー)」とは?

【Flutter】レイアウトボックス一覧|SizedBox・FittedBox・ConstrainedBox・LimitedBox・FractionallySizedBox

Flutterのレイアウトボックスの種類と使い方が知りたい

今回はこんな悩みを解消します。

本記事ではFlutterの主なレイアウトボックスであるSizedBox・FittedBox・ConstrainedBox・LimitedBox・FractionallySizedBoxの特徴と使い方について解説していきます!

目次

SizedBox

SizedBoxの基本的な使い方について解説します。

SizedBoxの主な役割には「ウィジェットのサイズ調整」と「余白調整」の2つがあります。

ウィジェットのサイズ調整

ウィジェットの中にはCardのようにwidthプロパティ、heightプロパティが備わってなくサイズ調整できないウィジェットがあります。

そんな場合はSizedBoxのchildプロパティにサイズ調整したいウィジェットを渡し、SizedBoxのwidthプロパティ、heightプロパティで代わりにサイズを調整できます。

SizedBox(
  height: 100,
  width: 200,
  child: Card(...),
)
画像のサンプルコード
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter')),
      body: Center(
        child: SizedBox(
          height: 100,
          width: 200,
          child: Card(
            color: Colors.blue,
            child: Center(
              child: Text(
                'Hello World',
                style: TextStyle(
                  fontSize: 30,
                  color: Colors.white,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

余白調整

SizedBoxではchildプロパティを使用せずwidthプロパティ、heightプロパティの片方もしくは両方を使用して余白調整ができます。

使用例としてColumnで並べているウィジェット間の余白の微調整が挙げられます。

Column(
  children: [
    WidgetA(),    
    SizedBox(height: 100),
    WidgetB(),
    SizedBox(height: 50),
    WidgetC(),
  ],
),

FittedBox

FittedBoxの基本的な使い方について解説します。

FittedBoxのchildプロパティにサイズをスケーリングしたいウィジェットを渡し、fitプロパティの引数にBoxFitウィジェットの列挙型(enum)を渡すことで次のような様々なサイズを指定できます。

列挙型意味
BoxFit.fill子ウィジェットの縦横比を歪めてでも、親ウィジェットいっぱいに広げる
BoxFit.contain子ウィジェットの縦横比を維持したまま、親ウィジェット内に収まるサイズまで広げる
BoxFit.cover子ウィジェットの縦横比を維持したまま、親ウィジェット全体を全てカバーするサイズまで広げる
BoxFit.fitWidth子ウィジェットの縦横比を維持したまま、親ウィジェットの横幅いっぱいまで広げる
BoxFit.fitHeight子ウィジェットの縦横比を維持したまま、親ウィジェットの高さいっぱいまで広げる
BoxFit.scaleDown子ウィジェットの縦横比を維持したまま、親ウィジェット内に収まるまでサイズを小さくする
BoxFit.none子ウィジェットの元のサイズで親ウィジェットに表示する
FittedBox(
  child: MyWidget(),
  fit: BoxFit.contain,
),
画像のサンプルコード
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter')),
      body: Center(
        child: Container(
          color: Colors.blue,
          height: 150,
          width: 350,
          child: FittedBox(
            fit: BoxFit.contain,
            child: Container(
              color: Colors.amber,
              child: Text(
                "Hello World",
                style: TextStyle(
                  fontSize: 50,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

ConstrainedBox

ConstrainedBoxの基本的な使い方について解説します。

ConstrainedBoxのchildプロパティに最大値または最小値を設定したいウィジェットを渡し、constraintsプロパティにBoxConstraintsウィジェットを渡します。

BoxConstraintsのmaxWidthプロパティで横幅の最大値、maxHightプロパティで高さの最大値、minWidthプロパティで横幅の最小値、minHightプロパティで高さの最小値を設定します。

ConstrainedBox(
  constraints: BoxConstraints(
    maxWidth: 300,
    maxHeight: 300,
    minWidth: 50,
    minHeight: 50,
  ),
  child: MyWidget(),
),
画像のサンプルコード
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter')),
      body: Center(
        child: ConstrainedBox(
          constraints: BoxConstraints(
            maxWidth: 300,
            maxHeight: 300,
            minWidth: 50,
            minHeight: 50,
          ),
          child: Text(
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Magna fermentum iaculis eu non diam phasellus. Varius quam quisque id diam vel quam elementum pulvinar etiam. Mattis molestie a iaculis at. Ultrices dui sapien eget mi proin sed libero. Fermentum iaculis eu non diam phasellus.",
            style: TextStyle(
              fontSize: 22,
              overflow: TextOverflow.fade,
            ),
          ),
        ),
      ),
    );
  }
}

LimitedBox

LimitedBoxの基本的な使い方について解説します。

LimitedBoxのchildプロパティの引数に最大値を設定したいウィジェットを渡し、maxHeightプロパティで高さの最大値、maxWidthプロパティで横幅の最大値を設定できます。

またLimitedBoxの性質についてですが、LimitedBoxのサイズ調整が有効になるのは親ウィジェットがColumnやRowのように範囲が無限の場合のみで、親ウィジェットがContainerなどのように範囲が定まっている場合は無効化されます。

LimitedBox(
  maxHeight: 250,
  child: ListView.builder(
    itemCount: 30,
    itemBuilder: (BuildContext context, int index) {
      return Center(
        child: Text("Hello World"),
      );
    },
  ),
),
画像のサンプルコード
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            "Top",
            style: TextStyle(fontSize: 30),
          ),
          LimitedBox(
            maxHeight: 250,
            child: Container(
              color: Colors.amber,
              child: ListView.builder(
                itemCount: 30,
                itemBuilder: (BuildContext context, int index) {
                  return Center(
                    child: Text(
                      "Hello World",
                      style: TextStyle(
                        fontSize: 30,
                        height: 2,
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
          Text(
            "Bottom",
            style: TextStyle(fontSize: 30),
          ),
        ],
      ),
    );
  }
}

FractionallySizedBox

FractionallySizedBoxの基本的な使い方について解説します。

親ウィジェットに対して相対的な割合でサイズ調整したい子ウィジェットをFractionallySizedBoxのchildプロパティの引数として渡し、FractionallySizedBoxのwidthFactorプロパティとheightFactorプロパティで親ウィジェットの大きさを1とした時の割合でサイズ調整できます。

仮に親ウィジェットの横幅が「300」、widthFactorを「0.5」とした場合、子ウィジェットの横幅は親ウィジェットの50%に当たる「150」になります。

またFractionallySizedBoxでサイズを調整した場合、子ウィジェットで指定したサイズは無効化されます。

Container(
  width: 300,
  height: 200,
  child: FractionallySizedBox(
    widthFactor: 0.5, //親ウィジェットの50%の高さ
    heightFactor: 0.8, //親ウィジェットの80%の横幅
    child: Container(
      width: 200, //無効化される
      height: 100, //無効化される
    ),
  ),
),
画像のサンプルコード
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter')),
      body: Center(
        child: Column(
          children: [
            SizedBox(
              height: 100,
            ),
            Container(
              color: Colors.amber,
              width: 300,
              height: 200,
              child: FractionallySizedBox(
                widthFactor: 0.5,
                heightFactor: 0.8,
                child: Container(
                  width: 200, //無視される
                  height: 100, //無視される
                  color: Colors.pink[300],
                  alignment: Alignment.center,
                  child: Text(
                    '縦:80%\n横:50%',
                    style: TextStyle(fontSize: 30, color: Colors.white),
                    textAlign: TextAlign.center,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

まとめ

今回はFlutterにおける主なレイアウトボックスの種類と基本的な使い方について解説しました。

SizedBox・FittedBox・ConstrainedBox・LimitedBox・FractionallySizedBoxの特徴と使い方についてそれぞれ別記事で詳細に解説しているのでよかったらこちらもご覧ください。

目次