🌟

【コード例で学ぶ】Flutter「Basic Widgets」完全ガイド

に公開

はじめに

皆さん、こんにちは。

この記事では、Flutterの公式で紹介している「Basic Widgets」内のウィジェットについて例も交えて紹介しています。

初心者必見の内容となっております。

https://docs.flutter.dev/ui/widgets/basics

サンプルコード

https://github.com/peter-norio/flutter/tree/main/basic_widgets_samples

画面に表示されるウィジェット

概要

  • 実際に目に見えるコンテンツを描画する
  • 画像や文字としてユーザーに情報を伝える役割
  • レイアウトウィジェットの子として組み込まれる

画面に表示されるウィジェットは、情報や体験をユーザーに伝えるための窓口であり、アプリの「見た目」を構成する最小単位の要素群です。

これらのウィジェットの主な役割は、画像、アイコン、文字といった形で情報をユーザーに直接伝えることです。

これらのウィジェットは単独で存在するというよりは、ほとんどの場合、ColumnRowContainerのような「レイアウトウィジェット」の子として組み込まれます。これにより、画面上のどこに、どのくらいのサイズで表示されるかが決まります。

Icon(アイコン)

アイコン図形を描画するウィジェットです。直感的なアイコンを通じてユーザーに機能や状態を伝えます。
https://api.flutter.dev/flutter/widgets/Icon-class.html

引数(よく使うものをピックアップ)

  • IconData? icon: 必須、Icons クラスの定数でアイコンを指定
  • 名前付き引数(省略可能)
    • Color? color: Colors クラスの定数でアイコンの色を指定
    • double? size: アイコンの大きさを数値(ピクセル)で指定

// ピンク色で、サイズが50ピクセルの、ハートのアイコン
Icon(Icons.favorite, color: Colors.pink, size: 50)

Image(画像)

指定した画像を画面に表示するウィジェットです。プロジェクト内に配置した画像だけでなく、ネットワークやデバイス上のファイルなどを使うことができます。

https://api.flutter.dev/flutter/widgets/Image-class.html

コンストラクタの種類ごとの記述方法

  • Image.asset(): プロジェクト内に組み込まれた画像を表示

    • pubspec.yamlで画像ファイルのパスを定義する必要がある
    flutter:
      assets:
        - assets/images/screen_shot.png
    
    Image.asset('assets/images/screen_shot.png', height: 50,),
    
  • Image.network(): インターネット上から画像をダウンロードして表示

    Image.network('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDZXOmYQwj6D4cM5beEMORXxl9wj1b_j_-Y-MjuhpDg2VroOp7iOfEH12rsgO4eJwpHcwL_XGwk6QmdXhyphenhyphencuNy6VWwE1_oXYnIJFWIQ-Q5uphF5GvVd6lyp5hwhxexTFzQu7IQJcl6fxng/s400/buranko_boy_smile.png', height: 50,)
    
  • Image.file(): デバイスに保存されている画像を表示

    Image.file(File('デバイス内のファイルパス'))
    
  • Image.memory(): メモリ上にバイトデータとして存在する画像を表示

    Image.memory('Base64エンコードされた文字列(型はUnit8List型)')
    

引数(よく使うものをピックアップ)

  • 名前なし引数では各コンストラクタに応じた画像の指定(必須)
  • 名前付き引数(省略可能)
    • double? width: 横幅をピクセル単位で指定
    • double? height:縦の高さを、ピクセル単位で指定
    • BoxFit? fit: 領域内にどのように表示するか
      • BoxFit.cover: アスペクト比を崩さす領域全体を覆うよう表示し、はみ出した部分は切り取られる
      • BoxFit.contain: アスペクト比を維持して全体が収まるように拡大縮小する
      • BoxFit.fill: アスペクト比を崩して領域の幅と高さに合わせて引き伸ばし、全体を埋めるよう表示する

Text(テキスト)

文字を画面に表示するためのウィジェットです。タイトル、見出し、説明文、ボタンのラベル、リストの項目など、あらゆる場所で利用されます。

https://api.flutter.dev/flutter/widgets/Text-class.html

引数(よく使うものをピックアップ)

  • 表示する文字列(必須)
  • 名前付き引数(省略可能)
    • double? width: 横幅をピクセル単位で指定
    • TextStyle? style: 文字の見た目(フォントサイズ、色、太さなど)
    • TextAlign? textAlign: 領域内でどのように配置されるか(左寄せ、中央寄せ、右寄せなど)
    • int? maxLines: 表示するテキストの最大行数を制限
    • TextOverflow? overflow: 領域にテキストが収まりきらない場合の表示方法を決定
      • TextOverflow.ellipsis: はみ出た部分を「...」で省略
      • TextOverflow.fade: はみ出た部分をフェードアウト
      • TextOverflow.clip: はみ出た部分を単に切り取り

シンプルな例

Text('文字を表示')

様々に設定している例

Text(
  'これは、非常に長いテキストの例です。指定された領域に収まりきらない場合に、どのようにテキストが処理されるかを示すために、意図的に長くしています。フォントサイズ、色、太さ、配置、そして行数制限とオーバーフローの挙動に注目してください。',
  style: TextStyle(
    fontSize: 18.0, // 文字の大きさ
    color: Colors.blue, // 文字の色
    fontWeight: FontWeight.bold, // 文字の太さ
  ),
  textAlign: TextAlign.center, // テキスト全体を領域内で中央揃え
  maxLines: 4, // 最大表示行数を4行に制限
  overflow: TextOverflow.ellipsis, // 4行を超えた場合は「...」で省略
),

:::messsage

引数の値が特殊なデータ型でかつ、定数を使って設定されているのは、想定外の設定値が渡ってこないようにするための設計だと思われます。

textAlign: TextAlign.centerなどがまさにそうです。

:::

Placeholder(ダミーの箱)

開発中にレイアウトを試す際の「仮置き」として使うシンプルな箱型でバツ印が引かれた見た目をしています。

https://api.flutter.dev/flutter/widgets/Placeholder-class.html

引数(よく使うものをピックアップ)

  • 名前付き引数(省略可能)
    • Color? color: 背景色とバツ印の線の色を指定

Placeholder()

配置方向を管理するウィジェット

概要

  • 子ウィジェットを横や縦方向に並べる役割
  • レイアウト関連の中でも複数の子ウィジェットを管理する
  • メイン軸、クロス軸に沿った配置の調整ができる

コンテンツを並べるために不可欠なのが、配置方向を管理するウィジェットです。

これらのウィジェットは、複数の子ウィジェットを管理します。単一のウィジェットを配置するだけでなく、複数の要素をグループ化し、整理して並べるために利用します。

主なウィジェットにColumnRowがあり文字通り縦方向と横方向に並べる際に利用します。これらはシンプルな縦横の概念だけでなく。メイン軸とクロス軸という概念を使って、子ウィジェットの配置を細かく調整できます。

Columnではメイン軸が縦、クロス軸が横となり、Rowではメイン軸が横、クロス軸が縦となります。

これにより、子ウィジェットの並び順や、軸に対する寄せる位置(開始、中央、終了など)、要素間のスペースの分配(均等に配置するなど)を指定することができます。

Column(縦並び)

複数の子ウィジェットを上から下へ縦方向に一列に並べて配置するためのレイアウトウィジェットです。

リストや、フォームの入力項目など、要素を縦に積み重ねて表示したい場合に便利です。Column自体は見た目を持たず、子ウィジェットの配置を管理する「骨組み」の役割を果たします。

https://api.flutter.dev/flutter/widgets/Column-class.html

引数(よく使うものをピックアップ)

  • List<Widget> children : 表示するウィジェットのリストを指定
    • require が指定されていないので必須ではないが、この引数がなければ何もしないので、事実上の必須引数
  • 名前付き引数(省略可能)
    • MainAxisAlignment mainAxisAlignment: メイン軸(縦方向)に沿って配置を決める
    • CrossAxisAlignment crossAxisAlignment: クロス軸(横方向)に沿って配置を決める
    • MainAxisSize mainAxisSize:メイン軸(縦方向)で、どれくらいのスペースを占めるか

// 自身の高さを子要素の分だけ最小限にし、その中で緑色の四角を縦横どちらも中央に配置して表示
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.center,
  mainAxisSize: MainAxisSize.min,
  children: [
    Container(
      width: 50,
      height: 50,
      color: Colors.green,
      child: Text('col1'),
    ),
  ],
),

Row(横並び)

複数の子ウィジェットを横方向(左から右へ)に一列に並べて配置するためのレイアウトウィジェットです。

ナビゲーションボタンや、アイコンとテキストの組み合わせなど、要素を横に並べて表示したい場合に便利です。Row自体は見た目を持たず、子ウィジェットの配置を管理する「骨組み」の役割を果たします。

https://api.flutter.dev/flutter/widgets/Row-class.html

引数(よく使うものをピックアップ)

  • List<Widget> children : 表示するウィジェットのリストを指定
    • require が指定されていないので必須ではないが、この引数がなければ何もしないので、事実上の必須引数
  • 名前付き引数(省略可能)
    • MainAxisAlignment mainAxisAlignment: メイン軸(横方向)に沿って配置を決める
    • CrossAxisAlignment crossAxisAlignment: クロス軸(縦方向)に沿って配置を決める
    • MainAxisSize mainAxisSize:メイン軸(縦方向)で、どれくらいのスペースを占めるか

// 自身の幅を子要素の分だけ最小限にし、その中で灰色の四角を縦横中央に並べて表示します。
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.center,
  mainAxisSize: MainAxisSize.min,
  children: [
    Container(
      width: 50,
      height: 50,
      color: Colors.grey,
      child: Text('Row1'),
    ),
  ],
),

ウィジェットの基本構造

概要

  • 画面上部のバーや中心的な描画領域など基本構造を提供
  • Scaffoldウィジェットで画面全体の基本構造を提供
  • Scaffold内にAppBar を配置し上部のバーを管理

Flutterでアプリの画面を構築する際、Scaffoldで基本構造を定義します。画面上部のアプリバー、中心的なコンテンツを描画する本体領域、そして下部のナビゲーションバーやフローティングアクションボタン、サイドメニューといった、画面の基本的な構造を提供します。

Scaffoldは画面全体の土台となるウィジェットであり、Scaffoldを使うことで、複雑なレイアウトを一から組み立てる手間なく、Material Designに準拠した画面構造を作成できます。

ScaffoldappBarプロパティにAppBarウィジェットを配置すると、画面の最上部に表示されるバーとして機能します。

Scaffold(画面の基本構造)

画面を作る際の「基本の土台」となるウィジェットです。アプリ画面の基本的な構成要素をまとめて配置する枠組みを提供します。

https://api.flutter.dev/flutter/material/Scaffold-class.html

引数(よく使うものをピックアップ)

  • 名前なし引数(位置引数)は無し
  • 名前付き引数(省略可能)
    • PreferredSizeWidget? appBar : 画面の最上部に表示されるバー(アプリバー)を設定
      • 通常はAppBarウィジェットを配置する
    • Widget? body : 画面の主要なコンテンツ領域を設定
    • Widget? floatingActionButton : 画面の右下に配置される円形のボタン(フローティングアクションボタン)を設定
      • 通常はFloatingActionButton ウィジェットを配置する
    • Widget? drawer : 画面の左端からスライドして出てくるサイドメニュー(ドロワー)を設定
      • 通常はDrawer ウィジェットを配置する
    • Widget? bottomNavigationBar : 画面の下部に表示されるナビゲーションバーを設定
      • 通常はBottomNavigationBarを配置する

// 画面の基本的なレイアウトを構成するウィジェット
Scaffold(
  // 画面上部に表示されるアプリバーを設定
  appBar: AppBar(title: Text('AppBar')),
  // 画面の主要なコンテンツ領域を設定
  body: Column(),
  // 画面右下に表示されるフローティングアクションボタンを設定
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Text('FAB'),
  ),
  // 画面左端からスライドして出てくるドロワー(サイドメニュー)を設定
  drawer: Drawer(
    child: ListView(
      children: [
        DrawerHeader(child: Text('DrawerHeader')),
        ListTile(title: Text('ListTitle1')),
        ListTile(title: Text('ListTitle2')),
      ],
    ),
  ),
  // 画面下部に表示されるナビゲーションバーを設定
  bottomNavigationBar: BottomNavigationBar(
    items: [
      BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
      BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add'),
    ],
  ),
);

AppBar(画面上部のバー)

Scaffoldの一部として、画面上部にアプリバーを描画し、その内部にタイトルやアクションなどのウィジェットを配置することもできます。

https://api.flutter.dev/flutter/material/AppBar-class.html

引数(よく使うものをピックアップ)

  • 名前なし引数(位置引数)は無し
  • 名前付き引数(省略可能)
    • Widget? title: アプリバーの中央に表示されるタイトル
      • ほとんどの場合、Textウィジェットを配置する
    • Widget? leading: タイトルの左側に表示されるウィジェット
      • ほとんどの場合は、アイコンを配置する
      • 例1サイドメニューを開くためのアイコン (IconButton)
      • 例2前の画面に戻るための矢印アイコン (BackButton)
    • List<Widget>? actions: タイトルの右側に表示されるリスト
      • 検索アイコンや設定アイコンなどを複数配置する
    • Color? backgroundColor: アプリバーの背景色を設定

appBar: AppBar(
  // アプリバーに表示されるタイトルウィジェット
  title: Text('AppBar'),
  // ツールバーの先頭に表示されるウィジェット
  leading: Builder(
    builder: (BuildContext context) {
      return IconButton(
        // アイコンウィジェット
        icon: Icon(Icons.menu),
        // ボタンが押されたときに実行されるコールバック
        onPressed: () {
          Scaffold.of(context).openDrawer();
        },
      );
    },
  ),
  // ツールバーの末尾に表示されるウィジェットのリスト
  actions: [
    // アイコンウィジェット
    IconButton(icon: const Icon(Icons.search), onPressed: () {}),
    // アイコンウィジェット
    IconButton(icon: const Icon(Icons.settings), onPressed: () {}),
  ],
  // アプリバーの背景色
  backgroundColor: Colors.lightBlue,
),

矩形領域の制御と装飾をするウィジェット

  • Container は万能に制御できるウィジェット
  • 単一の子ウィジェットを対象とする
  • 幅や高さ、余白などの矩形領域の制御をする
  • 色や影、背景などの装飾をする

Container(空白や装飾などの制御)

Containerウィジェットは、Flutterで矩形領域の制御と装飾を万能に行えるウィジェットです。

単一の子ウィジェットに対して調整を適用します。例えば、widthheightで幅や高さを明示的に指定したり、paddingmarginで余白を調整したりできます。

また、colorで色を設定したり、decorationプロパティを使って影を追加したりと、装飾も柔軟に行えます。

このように、Containerはレイアウトとスタイリングの両方において汎用性が高いウィジェットです。

https://api.flutter.dev/flutter/widgets/Container-class.html

引数(よく使うものをピックアップ)

  • 名前なし引数(位置引数)は無し
  • 基本的な名前付き引数(省略可能)
    • Widget? child: 管理対象の子ウィジェットを指定
      • レイアウトやスタイリングの対象なので事実上の必須
  • レイアウト関連の名前付き引数(省略可能)
    • AlignmentGeometry? alignment: 子ウィジェットの配置指定
      • 例: 中央、左上など
      • 通常はAlignment の定数を指定
    • EdgeInsetsGeometry? padding: 内側の余白を指定
      • EdgeInsetsの名前付きコンストラクタを指定
    • EdgeInsetsGeometry? margin: 外側の余白を指定
      • EdgeInsetsの名前付きコンストラクタを指定
    • double? width: 幅をピクセルで指定
    • double? height: 高さをピクセルで指定
  • スタイリング関連の名前付き引数(省略可能)
    • Color? color: 背景色を指定
      • decorationと同時に設定することはできない
    • Decoration? decoration: 背景装飾を指定
      • 例: BoxDecorationを使って、複雑な色、グラデーション、画像、ボーダー、角丸、影など

// 黒い線で囲まれた高さ50、幅100の四角い箱で、内側に10の余白があり、
// 「中央に配置」というテキストがその内側の中央に表示され、
// さらに外側に10の余白があります。
Container(
  alignment: Alignment.center,
  padding: EdgeInsets.all(10),
  margin: EdgeInsets.all(10),
  height: 50,
  width: 100,
  decoration: BoxDecoration(border: Border.all()),
  child: Text('中央に配置',),
),

操作を受け付けるウィジェット

概要

  • ユーザーからの入力やジェスチャーに反応する
  • 操作に応じて処理を起動できる

ユーザーからの入力やジェスチャーに反応し、それに応じて特定の処理を起動できます。

操作を受け付けるウィジェットは、タップ、長押し、ドラッグ、スワイプといった様々なユーザーの行動を検知し、アプリケーションがそれに応じた動作をするためのトリガーとなります。

これにより、単なる情報の表示だけでなく、ユーザーの操作に動的に反応する機能を提供できます。

ElevatedButton(立体的なボタン)

少し浮き上がったような影がついたボタンです。タップされると予め設定した処理を実行させることができます。

https://api.flutter.dev/flutter/material/ElevatedButton-class.html

コンストラクタ

コンストラクタの種類ごとの記述方法

コンストラクタの種類と固有の引数

  • ElevatedButton() : 標準的なコンストラクタ。ラベル付きボタンを用意する

    • Widget? child: 必須。ボタンに表示されるコンテンツを指定
    // 星アイコンと「ElevatedButton()」というテキストが表示されており、通常タップすると「ElevatedButton」というタイトルのダイアログが、長押しすると「LongPress」というタイトルのダイアログが表示される浮き上がるボタン
    ElevatedButton(
      onPressed: () {
        showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(title: Text('ElevatedButton'));
          },
        );
      },
      onLongPress: () {
        showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(title: Text('LongPress'));
          },
        );
      },
      child: const Row(
        // Rowが子にフィットするように最小限のサイズにする
        mainAxisSize: MainAxisSize.min,
        children: [Icon(Icons.star), Text('ElevatedButton()')],
      ),
    ),
    
  • ElevatedButton.icon() : アイコンとラベル付きボタンを用意

    • Widget? icon: ボタンに表示するアイコンを指定
    • Widget label: 必須。ボタンに表示するテキストを指定
    // 星アイコンと「ElevatedButton.icon()」というテキストが表示されており、タップすると「ElevatedButton.icon」というタイトルのダイアログが表示される浮き上がるボタン
    ElevatedButton.icon(
      onPressed: () {
        showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(title: Text('ElevatedButton.icon'));
          },
        );
      },
      icon: const Icon(Icons.star),
      label: const Text('ElevatedButton.icon()'),
    ),
    

引数(二つのコンストラクタ共通かつ、よく使うものをピックアップ)

  • 名前なし引数(位置引数)は無し
  • 名前付き引数(必須)
    • VoidCallback? onPressed: タップされたときに呼び出される関数を指定
  • 名前付き引数(省略可能)
    • VoidCallback? onLongPress: ボタンが長く押された(長押し)ときに呼び出される関数を指定

    • ButtonStyle? style: ボタンのスタイルを定義

      // 青い背景に黄色の文字「styled」が表示され、赤い太い枠線があり、コンテンツの周囲に10の余白が設けられた浮き上がるボタン
      ElevatedButton(
        onPressed: () {},
        style: ElevatedButton.styleFrom(
          // 背景色
          backgroundColor: Colors.blue,
          // 文字色
          foregroundColor: Colors.yellow,
          // 空白
          padding: EdgeInsets.all(10),
          // 枠線
          side: BorderSide(color: Colors.red, width: 5), 
        ),
        child: Text('styled'),
      ),
      

おわりに

FlutterのUIを構成する基本的なウィジェットを、その役割ごとに分類して解説しました。

  • 画面に表示されるウィジェット: IconImageTextPlaceholderのように、ユーザーに直接情報を伝える役割を持つウィジェット。これらは主に他のレイアウトウィジェットの子として配置されます。
  • 配置方向を管理するウィジェット: ColumnRowのように、複数の子ウィジェットを縦や横に並べ、配置を細かく調整するための「骨組み」となるウィジェット。
  • ウィジェットの基本構造: ScaffoldAppBarのように、アプリ画面全体の基本的な構造(アプリバー、ボディ、ドロワーなど)を提供するウィジェット。
  • 矩形領域の制御と装飾をするウィジェット: Containerのように、単一の子ウィジェットのサイズ、余白、背景、ボーダー、影といった視覚的な装飾を一手に引き受ける万能ウィジェット。
  • 操作を受け付けるウィジェット: ElevatedButtonのように、ユーザーのタップや長押しといったジェスチャーに反応し、アプリの機能を起動するウィジェット。

Discussion