What’s new in Flutter 3.47【日本語訳】




What’s new in Flutter 3.47

What’s new in Flutter 3.47

訳者 はじめに

Emma Twerskyさんによる「What’s new in Flutter 3.47」(原文)の日本語訳です。勝手に訳して、後から許可を取ります(笑)

はじめに

Flutter 3.47の新機能
Flutter 3.47の新機能

Flutter 3.47がリリースされました。今回のリリースでは、いくつかの魅力的な新機能が追加されています。

本日、スタンドアロンの material_ui および cupertino_ui パッケージの 1.0 リリースを発表します。これは、デザインシステムをコア SDK から切り離すという、大きなマイルストーンです。

また、パフォーマンスとツールの全般的な強化も行っています。今回のリリースでは、Impeller がデフォルトでデスクトップ版に導入され、iOS、macOS、Xcode 27 向けのパイプラインが整備され、Flutter Widget Previews が安定版へと移行しました。

それでは、ターミナルで flutter upgrade を実行して始めましょう。あるいは、このリリースの主な変更点について詳しく知りたい方は、以下を読み進めてください。


自分だけのUIアドベンチャーを選ぼう

デカップリングされたFlutterへの第一歩がここに:MaterialとCupertinoがスタンドアロンパッケージとして利用可能になりました!

Flutterの最大の強みのひとつは、MaterialおよびCupertinoウィジェットをピクセルパーフェクトにレンダリングできることです。しかし、これらのデザインライブラリは従来、コアSDK内に直接バンドルされていたため、開発の遅延を招き、貢献や最新状態の維持が困難になっていました。

今回のリリースでは、コアSDKにこれらのライブラリが引き続き含まれていますが、pub.devで正式にバージョン1.0に達したスタンドアロンの material_ui および cupertino_ui パッケージを、必要に応じて利用できるようになりました。

デザインロードマップの分離(オプトイン)

分離されたデザインシステムをオプトインすることで、デザインロードマップを自由に管理できるようになります。material_uicupertino_ui は現在 pub.dev 上で公開されているため、四半期ごとの Flutter SDK リリースとは独立して、独自の週次スケジュールでバグ修正や新しいコンポーネントをリリースすることができます。

デザインシステムの分離により、次のようなメリットが得られます:

  • Flutter SDKのバージョン全体をアップグレードすることなく、最新のCupertinoおよびMaterialウィジェットスタイルを使用できます。
  • コントリビューションや更新を、より迅速かつ頻繁に反映できるようになります。
  • スタイルに依存しないFlutterコアウィジェットカタログの基盤を築くことで、将来的にカスタムデザインシステムを構築しやすくなります。

移行方法

プロジェクトを新しいスタンドアロンパッケージに移行するには、次のコマンドを実行してください:

dart fix --apply --code=migrate_design_widgets

このツールは、package:flutter/material.dart および package:flutter/cupertino.dart からのインポートを、新しいスタンドアロンパッケージに自動的に更新します。

注: 移行ツールが pubspec.yaml の更新中に問題(初期段階の既知のバグ)に遭遇した場合は、手動で flutter pub add material_ui(および cupertino_ui を使用している場合はそれ)を実行し、その後もう一度 dart fix --apply を実行することで解決できます。

コア SDK 内の従来のデザインライブラリは、11月に予定されている秋の安定版リリースで正式に非推奨となる予定です。エコシステム内のパッケージを移行する場合は、このスタンドアロンパッケージへの移行をメジャーリリースとして扱ってください。

移行のギャップを埋める

エコシステムが新しいスタンドアロン設計ライブラリへ移行する際のギャップを埋めるため、material_ui および cupertino_ui には移行ユーティリティが同梱されています。MaterialUiCompatibilityBridge を使用すると、パッケージの依存関係の一部が依然としてレガシーなコア SDK のインポートを使用している場合でも、アプリケーションを直ちにスタンドアロンパッケージへ移行させることができます。

例えば、アプリを互換性ブリッジでラップすることができます:

    import 'package:material_ui/material_ui.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4)),
          ),
          builder: (BuildContext context, Widget? child) {
            return MaterialUiCompatibilityBridge(child: child!);
          },
          home: const HomeScreen(),
        );
      }
    }

ローカライゼーションの分離

この移行の一環として、flutter_localizations も分離されました。Material および Cupertino ウィジェットのローカライゼーション・デリゲートと翻訳済み文字列は、それぞれ package:material_ui および package:cupertino_ui 内に配置されるようになりました。

以前:

    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:flutter/material.dart';
    
    // ...
    localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
      GlobalCupertinoLocalizations.delegate,
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
    ],

これから:

    import 'package:material_ui/material_ui.dart';
    
    // ...
    localizationsDelegates: GlobalMaterialLocalizations.delegates,

localizationsDelegatesGlobalMaterialLocalizations.delegates に設定すると、Cupertino および Widgets のデリゲートも含まれるようになったため、セットアップが簡素化されます。

パッケージのアンバンドリングを示すアーキテクチャ図
ローカライゼーション構造の分離

貢献の受付開始

4月にMaterialおよびCupertinoライブラリへの貢献を一時停止したことで、スムーズな移行を実現することができました。material_uiおよびcupertino_uiで皆様をお待ちしているライブラリは、皆様がすでに使用しているものと同じものです。

凍結を解除する準備が整いましたので、新しいパッケージでは、今後定期的に修正や新機能が提供される予定です。現在は毎週のリリースを計画しています。また、これらのパッケージをコミュニティからの貢献に正式に開放できることを嬉しく思います。

Appleの次期アップデートに向けた準備

今秋に Xcode 27、iOS 27、macOS 27 がリリースされることを受け、Flutter がこれらのアップデートに対応できるよう、重点的に準備を進めてきました。ユーザーがリリース初日に予期せぬ問題に直面しないよう、今すぐ Apple のベータ版を使用してアプリのテストを行うことをお勧めします。

さらに、Xcode 27 に対応するため、サポート対象の OS の最小バージョンが引き上げられました:

Platform Previous minimum New minimum (Flutter 3.47+)
iOS 13 15
macOS 10.15 12

UIScene ライフサイクルの必須化

iOS 27 SDK では、すべての UIKit ベースのアプリにおいて UIScene ライフサイクルの採用が必須となりました。Xcode 27 でビルドされたアプリで UIScene を採用していない場合、起動時にアプリが起動しなくなります。

ほとんどのアプリでは、Flutter CLI がビルド中にこの移行を自動的に処理します。ただし、AppDelegate にカスタムネイティブコードが含まれている場合や、レガシーなアプリケーションライフサイクルに依存しているプラグインを使用している場合は、手動での移行が必要になります。そのような場合は、『UIScene/Delegate 採用ガイド』に従って手動で移行を行う必要があります。

Intel Macの段階的廃止

AppleのApple Siliconへの移行に伴い、FlutterはIntelベースのMacに対するサポートを段階的に終了しています。Intelハードウェア上での自動テストの実行を無効化し、Flutter CLIではIntelホスト上でビルドする場合やデュアルアーキテクチャを対象とする場合に警告を表示するようになりました。これらの警告は、今後のリリースでエラーに変更される予定です。

flutter config --enable-macos-arm64-only を実行することで、今すぐARM64専用のmacOSアプリをビルドするように設定できます。

Swift Package Managerの進捗状況

コミュニティはSwift Package Managerへの移行において目覚ましい進捗を遂げており、iOSプラグインのトップ100のうち92個がすでに移行済みです。以前にSwift Package Managerを無効にしていた場合は、flutter config --enable-swift-package-manager を実行して再有効化できます。

CocoaPodsは現在メンテナンスモードにあるため、SwiftPMへ移行していないプラグインは、いずれ動作しなくなります。また、移行されていないプラグインは pub.dev のスコアも低くなります。プラグインをメンテナンスしている場合は、移行ガイド を参照し、詳細については以前のブログ記事をお読みください。

また、今回のリリースではビルド時間が最適化されています。これは、コミュニティのコントリビューターである @lukemmtt 氏が、ビルドプロセスの早い段階で不要な SwiftPM パッケージスキームをフィルタリングすることで、ビルドパイプラインを改善してくれたおかげです。

デフォルトでの Wasm 対応に向けた道筋

現在、Flutter Web アプリケーションで WebAssembly (Wasm) をデフォルトで有効にし、ブラウザ上でネイティブ並みのパフォーマンスを実現できるよう、積極的に取り組んでいます。まだ Web アプリで Wasm をテストしていない場合は、リリースビルドコマンドに --wasm フラグを指定することで、今すぐ有効にすることができます:

flutter build web --release --wasm

この移行の準備を進めるにあたり、Wasm ではレガシーな dart:html ライブラリがサポートされていないため、コードベースを新しい JS 相互運用パッケージ(package:web)に移行する必要がある点にご留意ください。プロジェクトのパッケージ依存関係をアップグレードすることで、こうしたレガシーな相互運用に関する問題は多くの場合、自動的に解決されます。

大規模なWebアプリケーションのスケーラビリティ向上を支援するため、今回のリリースではWasmにおける遅延読み込みの実験的サポートも導入されました。メインチャネルでフラグを有効にすることで利用可能となり、これによりWasmアプリケーションをより小さなモジュールに分割して遅延読み込みを行うことができ、初期読み込み時間を最適化できます。

flutter build web --release --wasm --enable-wasm-deferred-loading

Impellerにより、デスクトップにも最先端のグラフィックスが登場

私たちは、デスクトッププラットフォームを高性能グラフィックスの第一級のターゲットにすることに尽力しています。Flutter 3.47では、ImpellerがmacOS、Windows、Linuxのデフォルトのレンダラーとなります。

Impellerをご存じない方のために説明すると、これはSkiaに代わるものとしてゼロから構築された、Flutterの次世代レンダリングエンジンです。Impellerは、最新のハードウェアAPI(macOSのMetalや、WindowsおよびLinuxのVulkanなど)をターゲットとすることで、実行時に動的にシェーダーをコンパイルするのではなく、ビルド時に固定されたシェーダーセットをコンパイルします。これにより、アニメーションが最初に再生される際に発生する「シェーダーコンパイルによるカクつき」と呼ばれる一瞬の遅延が解消され、最初のフレームから一貫して滑らかな遷移が実現されます。詳細は、Impellerレンダリングエンジンのドキュメントをご覧ください。

Impellerを一時的に無効にする必要がある場合は、以下の手順に従ってください:

  • macOS:Info.plist内でFLTEnableImpellerfalseに設定します。
  • Windows:main.cppproject.set\_impeller\_switch(flutter::ImpellerSwitch::Disabled)を追加します。
  • Linux: my_application.cc内で fl_dart_project_set_enable_impeller(project, FALSE) を呼び出してください。

フォールバックオプションは今後のリリースで削除される予定ですので、Skiaの使用に戻す必要がある場合はバグ報告を行ってください。また、macOSでは「ワイドガマットカラー」がデフォルトで有効になり、対応ハードウェア上で豊かで鮮やか、かつ正確な色再現を実現します。

実験的なマルチウィンドウ機能の進捗

Canonical との提携、およびメンテナーの @robert-ancell@mattkae のご協力により、実験的なデスクトップウィンドウ API を拡張しています。Linux および Windows ではポップアップウィンドウがサポートされるようになり、ネイティブなコンテキストメニューやユーティリティパレットを構築できるようになりました。

Popup windows on Win32
Win32 でのポップアップウィンドウ

また、プラットフォーム固有のコントローラーで windowHandle を照会することで、基になるネイティブウィンドウ(HWNDNSWindow、または GtkWindow)への直接ポインタを取得できるようになりました。これにより、Windows でのドッキング可能なペインなど、高度なネイティブ機能へのアクセスが可能になります。例えば、@orestesgaolin が提供したこのドッキング可能なペインのデモが挙げられます:

Dockable Panes demo
ドッキング可能なペインのデモ

また、ウィンドウのフォーカスや表示に関するいくつかのバグも修正しました。Windowsでは、ウィンドウをアクティブにしても、背景のウィンドウが前面に表示されたり、アプリの再開時にフォーカスが奪われたりすることがなくなりました。これは、コントリビューターの @9AZX のおかげで実現しました:

Window focus and realization fix on Windows
ウィンドウのフォーカスと実体化の修正

Linuxにおいて、マルチウィンドウの作成時、コンポジターから最初のフレームを受け取る前にウィンドウを明示的に実体化するようになりました。これにより、初期のレンダリング警告やコンポジターのアサーションが修正されました。

また、コンテンツに合わせて自動的にサイズが調整される通常ウィンドウやダイアログウィンドウを作成できる、新しい「sized-to-content」APIも追加しました。

デスクトップ向けのフレーバー

WindowsおよびLinuxで、Flutterのフレーバーがサポートされるようになりました。
たとえば、pubspec.yamlファイルで、フレーバーごとに異なるアセットを使用できるようになります:

flutter:
  assets:
    - path: assets/flavor_a/images
      flavors:
        - flavor_a
    - path: assets/flavor_b/images
      flavors:
        - flavor_c

--flavor オプションを使用して、フレーバーを指定します。例:

  • flutter build windows --flavor flavor_a
  • flutter build linux --flavor flavor_a

@AngeloAvv](https://github.com/AngeloAvv) さん、素晴らしいご貢献をありがとうございました!

デスクトップでのテキスト表示の鮮明化

デスクトップの画面は、モバイルディスプレイに比べてピクセル密度が低い場合が多い一方で、グラフィックス処理能力は高い傾向にあります。デスクトップ上でより鮮明なテキストと滑らかなベクター曲線を実現するため、Impellerを採用したFlutterエンジンは、macOS、Linux、およびWindowsにおいて、Signed Distance Function(SDF)レンダリングを採用するようになりました。

安定版プレビューとGenUIのアップデート

ウィジェットプレビューが安定版に

Flutter Widget Previewが安定版となり、アプリケーション全体をビルドしたり起動したりすることなく、個々のUIコンポーネントを即座にレンダリング、検査、反復処理できるようになりました。

この安定版リリースでは、以下の機能が利用可能です:

  • .widget_preview/ フォルダへのローカルプロジェクトキャッシュにより、繰り返し発生するセットアップのオーバーヘッドが排除され、起動時間が短縮されます。
  • 複雑なマトリックステストのためのテーマの逐次的な重ね合わせをサポートする抽象的な PreviewThemeData API により、より柔軟なテストが可能になります。
  • Webウィジェットのプレビュー時にWebアセットが自動的に同期され、ホストプロジェクトの web/ アセットが直接コピーされます。また、Flutter Webを使用する際は、カスタムテーマの適用や index.html ファイルのカスタマイズが自動的に行われます。

GenUIの継続的な進化

Flutterのエコシステムは、GenUIを使用してユーザー向けの新しいタイプのエージェンティックな体験を創出する開発者のニーズに応えるべく、進化を続けています。先日、genui パッケージのバージョン 0.10.0 がリリースされ、数多くの修正と新機能が追加されました。その中には以下のものが含まれます:

  • 式やカタログエントリなど、プロトコルに関連するクラスを一元化した新しい a2ui_core パッケージ。
  • A2UIのクライアントサイド関数のサポート。これにより、エージェントがクライアントに対して、検証、派生値の算出、その他の小さなタスクを、ラウンドトリップなしで実行させるよう指示できるようになります。

プラットフォーム体験の洗練

このセクションでは、すべてのプラットフォームにおける開発者およびユーザー体験を向上させるために、コミュニティと Flutter チームが貢献した重点的な改善点を紹介します。

Android

Android では、イベント処理中に修飾キー(Shift など)が固まってしまう仮想キーボードの問題を解決しました。キーレスポンダーは、仮想キーボード入力に対して物理キーの合成をスキップするようになり、キーボード操作がスムーズに行えるようになりました。

Android 依存関係マトリックス

安定したビルドを確保するため、Flutter 3.47 は以下の Android 依存関係のバージョンに対して検証されています:

  • Java: 17(必要最小バージョン)
  • Kotlin Gradle プラグイン (KGP): 2.4.0
  • Android Gradle プラグイン (AGP): 9.1.0(KGP 2.4.0 と互換性のある最新バージョン)
  • Gradle: 9.3.1(AGP 9.1.0に必要な最小バージョン)

今後のリリースにおいてもアプリケーションが正常にビルドされるようにするため、ビルドファイルでは Flutter SDK が提供する標準の API レベル変数を使用することを推奨します。このリリースでは、それらは以下のデフォルト値で設定されています:

  • flutter.compileSdkVersion (API 36)
  • flutter.targetSdkVersion (API 36)
  • flutter.minSdkVersion (API 24)

iOS および macOS

iOS 開発者にとって、コード署名のプロセスがより透明になりました。コミュニティメンバーの @alex-medinsh のおかげで、CLI では証明書を選択する際に「チーム ID」と「チーム名」の両方が表示されるようになりました。

さらに、コミュニティメンバーの @mozammal-hossain 氏により、署名に失敗した際のプロビジョニングプロファイルのエラーメッセージがより明確になり、トラブルシューティングが改善されました。

デスクトップ

デスクトッププラットフォームにも、特定の機能に対する改良が施されました。Windows では、韓国語テキスト入力時のキャレット位置の問題が解決されました(@CHOIgoung による貢献)。また、Windows プラグインでは、FlutterEngine::PostPlatformThreadTask を使用して、負荷の高いタスクをプラットフォームスレッドから切り離せるようになりました。Linux では、@CodeDoctorDE によって、スタイラスの回転および筆圧情報の報告機能が追加されました。

グラフィックスとエンジン

エンジンでは、OpenGLESを対象とするフラグメントシェーダーにおいて、テクスチャを読み込む際の座標反転の条件分岐が不要になりました。これは現在、頂点シェーダーで処理されます。詳細については、OpenGLESの「render-to-texture」に関する互換性変更ページをご覧ください。

フレームワークの洗練

最後に、フレームワーク自体もよりスムーズになり、主要なコンポーネントごとに改善が施されました:

アクセシビリティとセマンティクス: @xxxOVALxxx のおかげで、Android の高コントラストおよび色反転設定が自動的に検出されるようになりました(MediaQueryData.highContrast および MediaQueryData.invertColors)。Text.rich 内のネストされたテキストスパンは、セマンティクスツリー内のレイアウト順序と一致するようになりました。また、BlockSemantics に対してキーボードフォーカスのブロック機能が追加されました。

Androidのアクセシビリティ設定

Androidのアクセシビリティ設定

テキストと選択範囲: モバイル端末でのテキスト選択ハンドルは、わずかなスクロール中も安定して保持されるようになり、キーボードショートカットで開いている選択メニューを閉じられるようになりました。Androidでは、@JhonaCodesのおかげで、画面上部に位置している場合でも、選択ハンドルがコンテキストメニューを隠すことがなくなりました。

変更前 変更後
メニューと重なっている選択範囲のハンドル 選択ハンドルが正しく配置されている

また、空のスクロール可能なコンテナ内で選択が開始された際に発生していた SelectableRegion のクラッシュを修正し、フェードアウトされた選択可能テキストに見られる視覚的なハイライトの不具合も解決しました。これは @ikramhasan のおかげで実現しました。

修正前 修正後
ハイライト前 ハイライト後

ジェスチャーとスクロール: プラットフォームビューを介して埋め込まれたネイティブ iOS ビューにおけるジェスチャーの伝播が改善されました。EdgeDraggingAutoScroller は、アクティブなスクロールビューの ScrollPhysics を尊重するようになり、ロックされたリストでの自動スクロールが防止されます。

EdgeDraggingAutoScroller デモ
EdgeDraggingAutoScroller デモ

Core Widget の機能強化: useOriginalColors: true を使用して ImageIcon 内の元の色を保持したり、AnimatedCrossFade でクリッピングの挙動を指定したり、ImageStreamListener を使って画像ストリームのエラーを直接追跡したりできるようになりました。

アップグレードの準備は整いました

準備は万端、基盤も整いました。あとは、これらのアップグレードをローカルマシンに適用するだけです:

flutter upgrade

バックグラウンドで SDK の更新が行われている間に、皆さんへの(楽しい)課題をご用意しました:

  • 貢献者たちを紹介:ポップコーンを用意して、このリリースを可能にしてくれたコミュニティメンバーを称える新しい動画シリーズ「Introducing: Flutter Notable Commits」をご覧ください。
  • 詳細の確認:互換性破りの変更ページをざっと目を通し、スタンドアロンUIパッケージへの移行に備えましょう。

この新しく改良されたFlutterを使って、皆さんがどのようなものを作り上げてくれるのか、楽しみにしています!