[読書会]カスタムレイアウトについて

Flutter で、アダプティブな(適応型デザインが要求されるウィジェットには、

ダイアログ(Dialogs)
・ナビゲーション(Navigation)
・カスタムレイアウト(Custom layout)

があります。(このことは、docs.flutter.dev/ui/adaptive-responsive で述べられています)
以下は、(上記のうちの)カスタムレイアウト(Custom layout)関連のリファレンスです。

1.LayoutBuilder

親ウィジェットの制約(サイズなど)に基づいて、ウィジェットを構築するために使用します。
例えば、画面の幅が一定のサイズを超える場合に異なるレイアウトを表示したい場合に便利です。

(例)画面の幅が一定のサイズを超える場合に異なるレイアウトを表示します:
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
         title: const Text('LayoutBuilder Example')),
        body: const ResponsiveLayout(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (
       BuildContext context, 
       BoxConstraints constraints
      ) {
        //画面の幅に応じてレイアウトを変更する
        if (constraints.maxWidth > 600) {
          //画面の幅が600ピクセル以上の場合
          return Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const [
              Text('Wide Screen Layout'),
            ],
          );
        } else {
          //画面の幅が600ピクセル未満の場合
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const [
              Text('Narrow Screen Layout'),
            ],
          );
        }
      },
    );
  }
}
//このコードでは、LayoutBuilder を使って、
//・画面の幅が600ピクセル以上の場合は Row ウィジェット、
//・600ピクセル未満の場合は Column ウィジェット
//を表示するようにしています。
//これにより、画面サイズに応じて異なるレイアウトを提供できます。
  1. ConstrainedLayoutBuilder
  2. SliverLayoutBuilder
  3. RenderConstrainedLayoutBuilder
  4. AnimatedSwitcherLayoutBuilder

2.MediaQuery

デバイスの画面サイズや向きなどの情報を取得するためのウィジェットです。
これを使用することで、画面の高さや幅を簡単に取得できます。

(例)画面の高さや幅を取得している:
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('MediaQuery 使用例:')),
        body: const MediaQueryLayout(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    //画面のサイズを取得
    final screenSize = MediaQuery.of(context).size;
    final screenHeight = screenSize.height;
    final screenWidth = screenSize.width;

    return Center(
      child: Text(
        'Screen size: 
        ${screenWidth.toStringAsFixed(2)} x
        ${screenHeight.toStringAsFixed(2)}'
      ),
    );
  }
}
//MediaQuery を使用して、デバイスの画面サイズを取得し、画面の幅と高さをテキストとして表示しています。これにより、ウィジェットを表示する際にデバイスのサイズに合わせたカスタマイズが可能です。

MediaQueryData
debugCheckHasMediaQuery

3.AspectRatio

子ウィジェットのアスペクト比(幅と高さの比率)を固定するために使用されます。
例えば、正方形のウィジェットを常に正方形のまま表示する場合に使います。

(例)正方形のウィジェットを常に正方形のまま表示している:
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
         title: const Text('AspectRatio Example')
        ),
        body: const Center(
          child: AspectRatioBox(),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: 1.0, //アスペクト比を1:1(正方形)に設定
      child: Container(
        color: Colors.blue, //背景色を青に設定
      ),
    );
  }
}
//AspectRatio ウィジェットを使用して、子ウィジェットの幅と高さの比率を1:1に設定しています。これにより、親ウィジェットのサイズが変わっても、子ウィジェットは常に正方形のままになります。

4.FittedBox

子ウィジェットのサイズを親ウィジェットに合わせて拡大または縮小するために使用されます。
これにより、子ウィジェットの内容が親ウィジェット内に収まるように調整されます。

(例)子ウィジェットの内容が親ウィジェット内に収まるように調整している:
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('FittedBox Example')),
        body: const Center(
          child: FittedBoxContainer(),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200, //親ウィジェットの幅
      height: 100, //親ウィジェットの高さ
      color: Colors.grey, //親ウィジェットの背景色
      child: FittedBox(
        fit: BoxFit.contain, //子ウィジェットが親に収まるように調整
        child: Text(
          'This is a long text',
          style: TextStyle(fontSize: 30),
        ),
      ),
    );
  }
}
//このコードでは、FittedBox を使用して、テキストが親ウィジェットのサイズに合わせて拡大縮小されるようにしています。FittedBox がなければ、テキストが親ウィジェットを超えて表示されることがあります。

参照:
BoxFit  fit

参考:

BoxFit 列挙型

・fill :ソースのアスペクト比を歪めてターゲット ボックスを塗りつぶす。
・contain :ソースがターゲット ボックス内に完全に含まれる範囲で、可能な限り大きくする。
・cover :(内容ははみ出し全体は表示されないかもしれないが、とにかく)ターゲットボックスを全てカバーする。
・fitWidth :(隙間ができるかもしれないが)ターゲットボックスの横に合わせる。
・fitHeight :(隙間ができるかもしれないが)ターゲットボックスの縦に合わせる。
・none :ソースイメージのサイズ変更はしない。
・scaleDown :(隙間ができるかもしれないが)ターゲットボックス内に全部収める。

5.FractionallySizedBox

親ウィジェットのサイズに対する割合で子ウィジェットのサイズを指定するために使用されます。
例えば、以下の様に、親の幅の50%を子ウィジェットの幅とする場合に使えます。

(例)親の幅の50%を子ウィジェットの幅としている:
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('FractionallySizedBox Example')),
        body: const Center(
          child: FractionallySizedBoxContainer(),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return FractionallySizedBox(
      widthFactor: 0.5, //親の幅の50%に設定
      heightFactor: 0.3, //親の高さの30%に設定
      child: Container(
        color: Colors.green, //背景色を緑に設定
      ),
    );
  }
}
//このコードでは、FractionallySizedBox を使用して、親ウィジェットの幅の50%、高さの30%のサイズで子ウィジェットを表示しています。これにより、親ウィジェットのサイズに応じて子ウィジェットのサイズが変わります。

AnimatedFractionallySizedBox

コメントを残す