[読書会]Material3への移行

目次 index【閲覧時間3分】 click !!>>

1.まとめ

マテリアルライブラリMaterial3デザイン仕様に合わせて更新されました。変更点には、新しいコンポーネントコンポーネントテーマコンポーネントビジュアル更新などが含まれます。これらのアップデートの多くはシームレスです。
3.16(またはそれ以降のリリース)に対してアプリ再コンパイルすると、影響を受けるウィジェット新しいバージョン表示されます。しかし、移行を完了するには手作業も必要です。

2.移行ガイド

3.16リリース以前は、useMaterial3フラグをtrue設定することで、Material3変更参加することができました。
Flutter 3.16リリース(2023年11月)では、useMaterial3デフォルトtrueです。
ちなみに、useMaterial3false設定することで、アプリの動作をMaterial2に戻すことができます。 ただし、これは一時的な解決策に過ぎません。useMaterial3フラグとMaterial 2の実装は、Flutterの非推奨ポリシーの一部として最終的に削除される予定です。

(1)Colors(色)

ThemeData.colorSchemeデフォルトが、Material 3 Design 仕様に合わせて更新されました。

ColorScheme.fromSeed コンストラクタは、指定された seedColor から派生した ColorScheme を生成します。このコンストラクタによって生成される色は、Material3デザインシステムにおけるアクセシビリティのためのコントラスト要件を満たし、うまく調和するように設計されています。

3.16リリースにアップデートする際、正しいColorSchemeがないとUIが少し変に見えるかもしれません。これを修正するには、ColorScheme.fromSeedコンストラクタから生成されるColorSchemeに移行します。

移行前:
theme: ThemeData(
  colorScheme: ColorScheme.light(primary: Colors.blue),
),
移行後:
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),

コンテンツベースの動的な配色生成するには、ColorScheme.fromImageProvider 静的メソッドを使用します。配色を生成する例として、ネットワーク画像サンプルからのColorSchemeをご覧ください。

Flutter Material3の変更点には、新しい背景色が含まれます。 ColorScheme.surfaceTint高さのあるウィジェットを示します。 いくつかのウィジェットは異なる色を使用します。

(A-1)シードカラーを基にしたカラーパレット自動生成

Material 3 では、ColorScheme.fromSeed のようなデザインパターンを使って、シードカラーを基に色を自動生成することで、テーマ全体の整合性を保つことができますが、Material2では、テーマの各プロパティに具体的な色を設定する必要がありました。

故に、(非推奨ですが)もしMaterial2に戻したい場合は、以下の例の様に、カラーパレットを固定値設定に戻す必要があります。

(A-2)Material2に戻す場合(非推奨)

(Material3)カラーパレット生成による色設定例:
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
(Material2)固定値指定による色設定例1:
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple).copyWith(
    background: Colors.grey[50]!,
  ),
),
(Material2)固定値指定による色設定例2:
darkTheme: ThemeData(
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.deepPurple,
    brightness: Brightness.dark,
  ).copyWith(background: Colors.grey[850]!),
),

(B-1)surfaceTint と shadowColor による影や立体感の表現

ColorScheme.surfaceTint は、Material3で導入された新しいプロパティで、ウィジェットの elevation影や浮き上がり感を表現するために使われる色です。
(これまでは、shadowColor のみが影の表現に使われていましたが、Material 3 では surfaceTint が追加され、より柔軟で立体感のあるデザインが可能になりました)

これにより、surfaceTint と shadowColor を組み合わせることで、ウィジェットの影や立体感の表現をより細かく制御できます。

  • surfaceTint
     特定のウィジェット(例: Card や ElevatedButton)の背景色(surface)に対して色の階調を追加し、ウィジェットの浮き上がり感を視覚的に強調します。
  • shadowColor
     影そのものの色を指定するため、影がどのように見えるか(色や濃さ)を調整します。

(ア)Card、ElevatedButton 等のウィジェット

 surfaceTint shadowColor の両方を使って、ウィジェットの浮き上がり感を強調します。surfaceTint により、色の階調がつき、影に対する色の効果を加えます。

(イ)AppBar 等のウィジェット

 surfaceTint のみを使って elevation を表現することもあります。この場合、shadowColor を設定しなくても、surfaceTint を変えることで影の代わりに浮き上がり感を調整できます。

(B-2)外観について

Material 3 に移行することで、影の表現方法が変わるため、アプリの UI が以前(Material2)の見た目とは異なって感じることがあります。これを解消する為、次の様な設定を行うことで、Material2の動作に近づけることができます。

surfaceTint プロパティに Colors.transparent を設定して外観だけを旧マテリアルデザイン風に戻す場合

surfaceTint プロパティに Colors.transparent を設定することで、(Material3自体は維持したままで)部分的な色に関してのみ、Material 3 での影の効果を無効化できます。これにより、shadowColor のみを使って影を表現し、Material 2 の影の表現に近づけることができます。

(修正前)Material 3での影の効果が有効になっている場合の例:
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.deepPurple
  ),
),
(修正後)surfaceTint プロパティに Colors.transparent を設定することで、Material 3 での影の効果を無効化できます。これにより、shadowColor のみを使って影を表現し、Material 2 の影の表現に近づけることができます。
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.deepPurple
  ).copyWith(
    //ウィジェットの以前の動作に戻すには、
    //テーマのColors.transparentを
    //ColorScheme.surfaceTintに設定します。
    surfaceTint: Colors.transparent,
  ),
),

//この設定により、surfaceTint が無効化され、shadowColor のみを使って影の効果を表現します。
//これにより、Material 3 のデフォルトの浮き上がり感ではなく、Material 2 と同様の影の表現が適用されるため、以前の UI の動作に戻すことができます。

//surfaceTint と shadowColor の使い分けの理由
//surfaceTint は主に色の階調効果を加え、ウィジェットが浮き上がって見えるようにするためのものです。
//shadowColor は従来からの影色の設定を行うプロパティであり、Material 2 の影の表現方法を再現する場合は、shadowColor のみを使用することが望ましいです。

② (Material3を維持したまま)ウィジェットの輪郭や境界を強調したい場合

Material3を有効にしている場合、ColorScheme.shadow を使って shadowColor プロパティに色を設定すると、Material3で自動的に設計された視覚的な強調色を、境界の色(影の色)として使用できます。これにより、ウィジェットの境界がより視覚的に際立ち、背景や他のコンテンツと区別し易くなります。

・ウィジェットの影とコンテンツを区別する: ウィジェットが影(shadow)を持たないとき、コンテンツとウィジェットの境界が分かりにくくなることがあります。このとき、影の役割を果たす色を別途指定することで、ウィジェットの輪郭や境界を強調し、コンテンツとウィジェットを区別できるようにします。

・ColorScheme.shadow プロパティの設定: ColorScheme.shadow は、Material 3 で導入された ColorScheme の新しいプロパティのひとつです。これを使って、影の色を指定できます。特に、デフォルトで影の色が設定されていない場合(shadowColor が未設定のウィジェット)、この ColorScheme.shadow の色を shadowColor プロパティとして適用することが推奨されています。

・影の色を使った区別(強調): ColorScheme.shadow を設定することで、ウィジェットに影を持たせたり、影を無効にしたりする際に、影の役割を果たす色を適用できます。これは、ウィジェットが影を持たない場合や、Material 3 の surfaceTint による影の効果を無効にする場合に特に有用です。

たとえば、Card ウィジェットや ElevatedButton などのウィジェットがあるとします。これらのウィジェットは、通常 elevation を設定することで影が付き、他のウィジェットや背景と区別されるようになっています。

しかし、もし elevation を 0 に設定して影を取り除いた場合や、surfaceTint を無効にした場合(Colors.transparent を指定するなど)には、ウィジェットと背景との境界がわかりにくくなることがあります。

このとき、shadowColor に ColorScheme.shadow を指定することで、影を取り除いてもコンテンツの輪郭を際立たせる色を使って、ウィジェットと背景の区別を維持できます。

以下は、影を持たないウィジェットに対して shadowColor を設定する例です。

(旧マテリアルの頃から存在していた)shadowColor プロパティに、 (マテリアル3から使用できるようになった)ColorScheme.shadow で、 自動的に、視覚的に強調された色を、境界の色として、設定できます。
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple).copyWith(
    surfaceTint: Colors.transparent,
  ),
  appBarTheme: AppBarTheme(
   elevation: 4.0,
   shadowColor: Theme.of(context).colorScheme.shadow,
 ),
),

③ ElevatedButtonの外観について

Material2では、次の様な特定の色と影を使って、標準的なボタン表現を担っていました。

  • 背景色 (backgroundColor): ColorScheme.primary
  • 前景色(テキストの色など)(foregroundColor): ColorScheme.onPrimary
  • 影や浮き上がり感 (elevation): ElevatedButton のスタイルの特徴のひとつとして、影(elevation)を持つことでボタンが浮き上がって見せていた。

Material 3 では、ElevatedButton のスタイル設定に変更が加えられ、色設定が ColorScheme.primary ではなく、新しい色の組み合わせが使われるようになりました。

故に、もし、現マテリアルデザイン(Material3)を有効にした状態で、旧マテリアルデザイン(Material2)の様な ElevatedButton を使用したい場合、以下の様なカスタマイズが必要です。

Material3におけるElevatedButton:
ElevatedButton(
  onPressed: () {},
  child: const Text('Button'),
),
(カスタイズ後)外観をMaterial2風にする場合:
ElevatedButton(
  style: ElevatedButton.styleFrom(
   //背景色を ColorScheme.primary に設定
    backgroundColor: Theme.of(context).colorScheme.primary,
    //前景色(テキストの色)を ColorScheme.onPrimary に設定
    foregroundColor: Theme.of(context).colorScheme.onPrimary,
  ),
  onPressed: () {},
  child: const Text('Button'),
),

しかし、ElevatedButton を使用したい場合は、
上記カスタマイズによって旧デザイン風にするのではなく、
以下のFilledButton というウィジェットを使用して下さい。

FilledButton について:

Material 3 では、新しい FilledButton というウィジェットが導入されました。この FilledButton は、ElevatedButton の代わりに使われ背景色前景色のみを使ってボタンを表現し、影(elevation)や浮き上がり感を持たないスタイルが特徴です。

FilledButton は、以前の ElevatedButton のような単純な色の組み合わせ(primary と onPrimary)を持ちますが、影(elevation)や立体的な効果は含まれていません

FilledButton を使うことで、Material3で推奨されるフラットなボタンデザインを実現できます。

(2)Typography(文字体裁)

ここでは、Flutter 3.16 リリースにおける ThemeData.textTheme のデフォルト設定が Material3に基づいて変更されたことについて述べています。この変更により、フォントサイズやフォントウェイト、レター間隔(letter spacing)、行の高さ(line height)などのスタイルが、以前のバージョンとは異なる見た目や動作になったことが解説されています。

(A)Material2と Material3の TextTheme の違い

 Material2では、各 TextTheme のプロパティ(例:bodyText1、headline4 など)に設定されるデフォルトのフォントサイズやフォントスタイルが、Material 3 とは異なっていました。

 Material 3 では、これらのデフォルト値が一新され、フォントサイズが調整されたり、レター間隔や行の高さが変更されたことで、文字の見た目やテキストの折り返し(wrap)方が変わることがあります。

(B)フォント設定の変更に伴う影響

説明文にあるように、Material 3 の TextTheme の変更により、次のような影響が発生する可能性があります。

① フォントサイズの変更: デフォルトのフォントサイズが Material 2 よりも大きく(または小さく)なることで、同じ幅に収まる文字数が変わり、文字列の折り返し方に影響が出ます。

② レター間隔の変更: 文字と文字の間の間隔(レター間隔)が変更されたことで、以前は2行に収まっていたテキストが3行になったり、逆に1行に収まっていたものが2行になることがあります。

③ 行の高さの変更: 行の高さ(line height)が変わると、文字の行間が広がったり狭まったりし、視覚的な見やすさやレイアウトの変化につながります。

(C)コード例の解説

修正前のコード(Material 2 のスタイル適用時):
ConstrainedBox(
  constraints: const BoxConstraints(maxWidth: 200),
  child: Text(
    'This is a very long text that should wrap to multiple lines.',
    //デフォルトの bodyLarge スタイルを使用しています。
    style: Theme.of(context).textTheme.bodyLarge,
  ),
),

このコードでは、ConstrainedBox によって幅が 200 ピクセルに制限されているため、長い文字列が複数行に折り返されます。Material 2 の bodyLarge スタイルでは、フォントサイズや行の高さの設定が異なり、この文字列は 2 行に収まることが多いです。

修正後のコード(Material 3 のスタイル適用後):
ConstrainedBox(
  constraints: const BoxConstraints(maxWidth: 200),
  child: Text(
    'This is a very long text that should wrap to multiple lines.',
    //レター間隔を明示的に設定して折り返しを調整します。
    style: Theme.of(context).textTheme.bodyMedium!.copyWith(
      letterSpacing: 0.0,
    ),
  ),
),

このコードでは、bodyLarge スタイルが Material 3 のデフォルトに変更されたため、修正後のコードでは bodyMedium を使い、さらに letterSpacing(レター間隔)を 0 に設定しています。これにより、文字の間隔が狭まり、テキストの折り返し方が調整されます。

(D)なぜ letterSpacing を設定するのか?

Material 3 では、デフォルトの letterSpacing の値が Material 2 と異なり、特に bodyLarge や bodyMedium の文字スタイルでレター間隔が広がることがあります。この影響で、テキストが以前よりも多くの行に折り返されることが発生します。

※ letterSpacing: 0.0 を設定することで、文字の間隔を狭め、以前のバージョン(Material 2)と同様の折り返し方を再現できます。

(E)移行時の対応方法

もし、Material 2 でのデフォルトのスタイルを維持したい場合は、次のような対処が考えられます。

① letterSpacing や lineHeight を設定して調整する:
 各 TextStyle プロパティを copyWith を使ってカスタマイズし、文字の見た目を調整します。

② TextTheme 全体をカスタマイズする:
 アプリ全体で Material 2 の TextTheme に近いスタイルを維持したい場合は、ThemeData.textTheme を明示的に設定し、各スタイル(bodyText1、headline4 など)をカスタマイズすることができます。

(F)まとめ

① Material 3 の TextTheme では、デフォルトの文字スタイルが変更されたため、文字サイズや行間、レター間隔が異なり、テキストの見た目が変わる可能性があります。
② 修正前のコードと同じ見た目を再現したい場合は、letterSpacing や lineHeight を手動で調整することが必要です。
③ もし、Material 3 のデフォルトスタイルに適応したい場合は、そのまま TextTheme を使用し、デザインの変更を受け入れることも選択肢のひとつです。

このように、Material 3 への移行に際して、文字スタイルの変更がアプリのレイアウトや視覚的な表現に影響を与えることがありますので、適切なスタイル調整が求められます。

(3)Components(部品)

(A)BottomNavigationBar → NavigationBar への移行について

(B)Drawer → NavigationDrawer への移行について

(C)AppBar デザイン変更について

(ア)中型(medium) 及び 大型(large) の AppBar の導入

Marerial3では、AppBar の他に、SliverAppBar.mediumSliverAppBar.large が追加されました。
これらの AppBar は、標準の AppBar よりも大きなヘッドライン(見出し)を持ち、ユーザがスクロールする前にコンテンツの概要を視覚的に強調します。

CustomScrollView を使って SliverAppBar.medium とその下にあるコンテンツを組み合わせる例:
CustomScrollView(
  slivers: <Widget>[
    //medium サイズの SliverAppBar を追加
    const SliverAppBar.medium(
      //AppBar のタイトルを設定
      title: Text('Title'),  
    ),
    //SliverAppBar の下に配置されるコンテンツ
    SliverToBoxAdapter(  
      child: Card(
        child: SizedBox(
          //コンテンツの高さを設定
          height: 1200,  
          child: Padding(
            //コンテンツにパディングを設定
            padding: const EdgeInsets.fromLTRB(
              8, 100, 8, 100
            ),  
            child: Text(
              //サンプルテキストを表示
              'Here be scrolling content...',  
              //テキストスタイルを指定
              style: Theme.of(context).textTheme.headlineSmall,
            ),
          ),
        ),
      ),
    ),
  ],
)

(イ)影を使用せずに(AppBar とコンテンツの)視覚的な境界を提供

旧Material2では、AppBar の背景を分離する為に、ドロップシャドウ(影)が使用されていました。
Material3では、ColorScheme の surfaceTint プロパティを使用し、影を使用せずに AppBar とコンテンツの境界を視覚的に分離できます。これにより、Material 3 のデザインガイドラインに従ったフラットなデザインが実現されます。

Material 2 でのドロップシャドウ(影)を使用した AppBar の例:
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
        appBarTheme: AppBarTheme(
          //ドロップシャドウ(影)の高さを指定
          elevation: 4.0,
        ),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material 2 AppBar'),
        //AppBar の背景色を設定
        backgroundColor: Colors.blue,
      ),
      body: Center(
        child: Text(
          'Content under AppBar with drop shadow.',
          style: TextStyle(fontSize: 18),
        ),
      ),
    );
  }
}

以下のコードでは、AppBar の elevation プロパティを 0 に設定して影を表示せず、surfaceTint を使用して背景色の調整を行います。

Material 3 デザイン風の AppBar の例:
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        //Material 3 を有効化
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          //色の基準を設定
          seedColor: Colors.blue,
        ).copyWith(
          //surfaceTint を設定して背景色を調整
          surfaceTint: Colors.blue.shade200,
        ),
        appBarTheme: AppBarTheme(
          //影を表示しない
          elevation: 0,
          //背景色を薄い色に設定
          backgroundColor: Colors.blue.shade50,
        ),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Material 3 AppBar with surfaceTint'
        ),
      ),
      body: ListView.builder(
        itemCount: 20,
        itemBuilder: (context, index) {
          return Card(
            margin: const EdgeInsets.all(10),
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                'Item $index',
                style: Theme.of(context).textTheme.bodyMedium,
              ),
            ),
          );
        },
      ),
    );
  }
}

(D)TabBar の階層(2種類) と 水平方向配置制御

ここでは、Material3における新しい TabBar ウィジェットのデザインや機能について述べています。特に、TabBar が「primary」 と「secondary」の2種類に分類され、それぞれ異なる用途や階層を表現できるようになっていること、また新しい tabAlignment プロパティを使って TabBar の水平方向の配置を制御できることについて説明しています。

(ア)TabBarの階層(Primary タブバー、Secondary タブバー)

 Material 3 では、TabBar が「primary(プライマリ)」と「secondary(セカンダリ)」の2種類に分類されています。

Primaryプライマリ)タブバー:
 ページ全体のナビゲーションや主要なセクションの切り替えに使用されるタブバー。
例えば、アプリのトップレベルのナビゲーションや、主要な機能を分割する際に使用されることが多いです。

Secondaryセカンダリ)タブバー:
 ある特定のコンテンツエリア内で、さらに関連コンテンツを分割するために使用されるタブバー。
例えば、ユーザーのプロフィールページで「投稿」「フォロワー」「フォロー中」など、同じコンテンツの中でもさらなる詳細な分類を行う際に使います。

 これにより、アプリ内でのコンテンツの階層や関連性をより明確に表現できるようになっています。

(イ)TabBar.tabAlignment プロパティ

 TabBar に新たに追加された tabAlignment プロパティは、タブの水平方向の配置を制御するためのプロパティです。このプロパティを使うことで、以下のような配置を指定することができます。

TabAlignment.start
 タブを TabBar の左端(開始位置)に揃える。

TabAlignment.center
 タブを TabBar の中央に配置する(デフォルト設定)。

TabAlignment.end
 タブを TabBar の右端(終了位置)に揃える。

 この tabAlignment プロパティを使うことで、タブの配置をアプリのデザインに合わせて調整でき、ユーザーがナビゲーションする際の使い勝手を向上させることができます。

 以下のコードでは、TabBar の tabAlignment プロパティを TabAlignment.start に設定して、タブ左揃えにしています。また、isScrollable: true とすることで、タブがスクロール可能な状態(画面幅よりも多いタブが表示される)になっています。

tabAlignment プロパティの使用例:
AppBar(
  title: const Text('Title'),
  bottom: const TabBar(
    //タブを左揃えに設定
    tabAlignment: TabAlignment.start,
    //タブをスクロール可能にする
    isScrollable: true,
    tabs: <Widget>[
      Tab(
        //タブにアイコンを設定
        icon: Icon(Icons.cloud_outlined),
      ),
      Tab(
        icon: Icon(Icons.beach_access_sharp),
      ),
      Tab(
        icon: Icon(Icons.brightness_5_sharp),
      ),
    ],
  ),
),

(E)ToggleButtons → SegmentedButton への移行について

 ここでは、Flutter における SegmentedButton が新しい ToggleButtons のバージョンとして Material 3 で導入されたことについて述べています。

(ア)ToggleButtons と SegmentedButton の違い

 SegmentedButton は、ToggleButtons の改良版として Material 3 で導入されました。主な違いは以下の通りです。

① デザインの変更:

  • SegmentedButton では、角が完全に丸みを帯びたデザインが採用され、ToggleButtons よりも柔らかくフラットな外観になっています。
  • これにより、ボタンの一貫性と視認性が向上し、Material 3 のデザインガイドラインに合ったよりモダンな見た目を実現しています。

レイアウトの高さとサイズの違い:

  • SegmentedButton は、レイアウトの高さとサイズが ToggleButtons とは異なり、よりコンパクトでバランスのとれたサイズ設定になっています。

選択アイテムの管理方法

  • ToggleButtons では、isSelected プロパティを使用して、ボタンごとの選択状態をリスト(List)で管理していました。
  • SegmentedButton では、選択されたアイテムを Set(集合)を使って管理します。これにより、ボタンの選択状態をより柔軟かつシンプルに扱うことができ、複数の選択肢がある場合でも管理が容易になります。

(イ)コードの移行例(ToggleButtons から SegmentedButton へ)

移行前のコード(Material 2 の ToggleButtons の使用例):
enum Weather { cloudy, rainy, sunny }

ToggleButtons(
  //各ボタンの選択状態を List<bool> 型で指定しています。
  //この場合、3つのボタンがあり、それぞれ
  //「選択されていない」「選択されている」「選択されていない」
  //という状態を設定しています。
  isSelected: const [false, true, false],
  //ボタンが押されたときに
  //実行されるコールバック関数を指定しています。
  //引数 newSelection は
  //選択されたボタンのインデックスを表します。
  onPressed: (int newSelection) { 
  },
  //各ボタンのウィジェット
  children: const <Widget>[
    Icon(Icons.cloud_outlined),
    Icon(Icons.beach_access_sharp),
    Icon(Icons.brightness_5_sharp),
  ],
),
移行後のコード(Material 3 の SegmentedButton の使用例):
enum Weather { cloudy, rainy, sunny }

SegmentedButton<Weather>(
  //選択されたボタンを Set で管理
  //選択された項目を Set<Weather> 型で指定します。
  //ここでは Weather.rainy が選択された状態を表しています。
  //Set は、重複しないコレクションであるため、
  //選択されたアイテムを簡潔に管理できるメリットがあります。
  selected: const <Weather>{Weather.rainy},
  //選択状態が変更されたときの処理
  //ボタンの選択状態が変更されたときに
  //実行されるコールバック関数を指定します。
  //newSelection には、現在選択されているすべての項目
  //(Set<Weather> 型)が渡されるため、
  //複数選択の管理や状態の更新が容易です。
  onSelectionChanged: (Set<Weather> newSelection) {
  },
  //各ボタンの設定を Segment のリストとして管理
  //各ボタンの設定を ButtonSegment ウィジェットのリスト
  //として管理します。
  //ButtonSegment は value(ボタンの値)や 
  //icon(アイコン)、および label(ラベル)
  //などのプロパティを持ち、各ボタンの外観や値を指定できます。
  segments: const <ButtonSegment<Weather>>[
    ButtonSegment(
      icon: Icon(Icons.cloud_outlined),
      //ボタンの値を指定
      value: Weather.cloudy,
    ),
    ButtonSegment(
      icon: Icon(Icons.beach_access_sharp),
      //選択状態のボタン
      value: Weather.rainy,
    ),
    ButtonSegment(
      icon: Icon(Icons.brightness_5_sharp),
      value: Weather.sunny,
    ),
  ],
),

上記の詳細はこちら参照。

(ウ)Material 3 での SegmentedButton の活用例

 SegmentedButton は、ボタンの状態をより直感的に管理できるため、複数の選択肢を持つ UI の実装に向いています。例えば、以下のようなシチュエーションで役立ちます。

  • 設定画面やフィルタリングオプションの切り替え
  • リストビューやカードビューの選択(例: グリッド表示やリスト表示の切り替え)
  • カレンダーの日付選択やタイムラインの期間選択

Material 3 では、SegmentedButton を使用してより柔軟なデザインと選択状態の管理を実現でき、ユーザー体験を向上させることができます。

(エ)まとめ

 Material 2 の ToggleButtons は List で選択状態を管理していましたが、Material 3 の SegmentedButton では Set を使い、より簡潔に複数選択の状態を管理できるようになりました。また、SegmentedButton は丸みを帯びたデザインと異なるレイアウトの高さを持ち、視覚的にも一貫性のある表現が可能です。

(F)新しいコンポーネント

 ここでは、Material 3 における新しいコンポーネントの概要を紹介しており、これらのコンポーネントがどのように使用されるかを説明しています。

(ア)メニューバーと階層メニュー

Material 3 では、MenuBar や MenuAnchor を使ったデスクトップスタイルのメニューシステムが導入されています。これは、従来の PopupMenuButton といったクラスの代替として、デスクトップやウェブプラットフォーム向けに設計されており、マウスやキーボードでの操作がしやすいように設計されています。

  1. MenuBar と MenuAnchor の特徴:
    • MenuBar はメニューを表示するバーで、ファイルメニューや編集メニューなど、デスクトップアプリケーションで見られる上部メニューバーと似た役割を果たします。
      MenuAnchor はメニューを表示する位置を固定するためのウィジェットで、メニューが開かれる場所を指定します。
    • メニューは階層化されており、サブメニューを持つことができます。これは従来の PopupMenuButton とは異なる点です。
  2. 移行の必要性:
    • 既存のアプリケーションは PopupMenuButton のままでも問題ありませんが、デスクトップアプリケーションや Web アプリケーションでは、MenuBar や MenuAnchor の使用を検討することを推奨しています。

(イ)ドロップダウンメニュー

DropdownMenu は、テキストフィールドとメニューを組み合わせたコンポーネントで、一般的に「コンボボックス」とも呼ばれる UI 要素を提供します。

  1. DropdownMenu の特徴:
    • メニュー項目を選択できるのに加え、テキスト入力を使って項目を検索したりフィルタリングできる機能を持ちます。
    • DropdownButton の代替として使用することもできますが、DropdownButton からの移行は必須ではありません。
    • ユーザーは、タッチ操作、マウス操作、またはキーボード操作によってメニュー項目を選択できます。
  2. 利点:
    • 多くの選択肢からアイテムを選ぶ際に、ユーザーがキーボード入力で絞り込むことができるため、大量のデータを扱う場合に便利です。

(ウ)検索バーと検索結果表示バー

SearchBar と SearchAnchor は、ユーザーが検索クエリを入力し、アプリがそのクエリに応じた検索結果を表示するためのコンポーネントです。

  1. SearchBar の特徴:
    • 検索クエリを入力するためのテキストフィールド。
      ユーザーが文字を入力すると、リアルタイムでフィルタリングやオートコンプリートの結果を表示できます。
  2. SearchAnchor の特徴:
    • 検索結果を表示するためのコンテナ。
    • 検索結果を表示する位置を指定でき、検索クエリに対応する項目を強調表示したり、リスト表示を行えます。

(エ)バッジ

Badge コンポーネントは、子ウィジェット(通常はアイコン)に小さなラベル(+1 などの数文字)を装飾として追加するものです。

  1. Badge の特徴:
    • 主に NavigationDestination、NavigationRailDestination、NavigationDrawerDestination などのナビゲーション要素や、TextButton.icon のアイコン部分に装飾として使用されます。
    • 未読メッセージや通知の数を表示する際に用いられることが多く、ユーザーに追加情報を視覚的に提供します。

(オ)FiledButton と FilledButton.tonal

FilledButton と FilledButton.tonal は、ElevatedButton に似ていますが、影やエレベーションの変化を伴わないデザインを持ちます。

  1. FilledButton の特徴:
    • 背景色が設定されており、標準的なボタンとして使われます。
    • ElevatedButton の代わりに、よりフラットなボタンデザインを提供します。
  2. FilledButton.tonal の特徴:
    • より淡い背景色を持つバリエーションのボタンです。視覚的な強調度を下げる場合に使います。

(カ)FilterChip.elevated、ChoiceChip.elevated、ActionChip.elevated

これらは Chip の新しいバリエーションで、影と背景色を持つため、より強調された見た目の Chip を提供します。

  1. FilterChip.elevated:
    • フィルタリングオプションを表現する際に使用されます。
  2. ChoiceChip.elevated:
    • 単一の選択肢を選ぶ際に使用されます。
  3. ActionChip.elevated:
    • 特定のアクションを実行する際に使用されます(例: メールの送信や特定のタグを適用)。

(キ)Dialog.fullscreen

Dialog.fullscreen は、画面全体を覆うフルスクリーンダイアログで、通常はタイトル、アクションボタン、および画面上部のクローズボタンを含みます。

  1. 用途:
    • フォーム入力、詳細情報の表示、ユーザーに重要なアクションを促す際に使用されます。
    • 小さなポップアップダイアログよりも、より多くの情報を表示する必要がある場合に有効です。

(ク)まとめ

これらの新しいコンポーネントは、Material 3 のデザインガイドラインに沿っており、よりモダンで使いやすいインターフェースを提供します。特に、SegmentedButton や DropdownMenu などは、従来の ToggleButtons や DropdownButton の代替として、より直感的で柔軟なデザインが可能です。

また、各コンポーネントは、特定の状況やアプリの種類に合わせて使用されることを想定しており、デスクトップや Web プラットフォーム向けのアプリケーションに特に適しています。

3.タイムライン

ThemeData.useMaterial3

Material3 umbrella issue

コメントを残す