遷移至獨立的 material_ui 與 cupertino_ui 套件
Material 與 Cupertino 設計函式庫現已提供獨立套件, 讓設計系統與 Flutter SDK 解耦。
摘要
#
Material 與 Cupertino 設計函式庫現已提供獨立套件:
package:material_ui
與 package:cupertino_ui。
在 Flutter 3.47 中,開發者可以在框架內建設計函式庫正式棄用之前,
先行選擇採用這些套件。
背景
#
過去,Flutter 的 Material(package:flutter/material.dart)
與 Cupertino(package:flutter/cupertino.dart)元件 (Widget) 函式庫
直接內建於 Flutter SDK 核心之中。
雖然這讓開發者能輕鬆上手並取得像素級精準的元件,
但將設計系統內建於核心框架中也帶來了幾項挑戰:
- 元件的更新、錯誤修正與新元件,都綁定在 每季一次的 Flutter SDK 發布。
- 設計函式庫的貢獻與迭代速度, 比獨立的 Dart 套件更慢。
- 應用程式無法獨立於引擎與框架之外,單獨更新設計函式庫。
為了解決這些挑戰,設計系統現在已與核心框架解耦。
從 Flutter 3.47 開始,獨立的 material_ui 與 cupertino_ui 套件
1.0 版已發布於 pub.dev。
將設計系統解耦帶來以下幾項好處:
- 獨立的發布週期: 這些套件可以依自己的發布時程(規劃為每週發布) 推出錯誤修正、改進與新元件, 不需要完整升級 Flutter SDK。
-
更快速的貢獻:
社群成員可以直接在
flutter/packages儲存庫中為這些函式庫做出貢獻。 - 風格中立的核心: 解耦為風格中立的 Flutter 核心元件目錄奠定了基礎, 讓建立與維護自訂設計系統變得更容易。
自 Flutter 3.44 起,
核心 SDK 內 Material 與 Cupertino 套件的貢獻已被凍結。
package:material_ui 與 package:cupertino_ui 最初的 1.0.0 版本
與凍結時的框架程式碼一致,以提供無縫的過渡。
套件未來的發布將採用語意化版本(semantic versioning)
來標示主要、次要與修補更新。
框架內建的設計函式庫預定在未來的穩定版發布中正式棄用。
遷移指南
#
若要將專案從框架內建的設計函式庫遷移至獨立套件,
你可以使用自動化的 dart fix 工具,
或手動進行遷移。
使用 dart fix 自動遷移
#最快的遷移方式是搭配 dart fix 使用 migrate_design_widgets 修正規則:
dart fix --apply --code=migrate_design_widgets
此指令會自動將你的 package:flutter/material.dart 與
package:flutter/cupertino.dart 匯入
更新為對應的獨立套件匯入。
請再執行一次 dart fix,以確保套用所有其他自動遷移,
並處理 lint 警告,例如匯入排序。
手動遷移
#若要手動遷移,請依照下列步驟進行:
-
將獨立套件加入你的
pubspec.yaml相依套件:flutter pub add material_ui flutter pub add cupertino_ui -
更新 Dart 檔案中的匯入,改為參照新套件。
遷移前的程式碼:
dartimport 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';遷移後的程式碼:
dartimport 'package:cupertino_ui/cupertino_ui.dart'; import 'package:material_ui/material_ui.dart';
相容性橋接
#
在生態系轉換期間,你的應用程式可能相依於
仍然匯入舊有框架內建函式庫
(package:flutter/material.dart 或 package:flutter/cupertino.dart)的第三方套件。
為了讓你的應用程式能立即遷移至獨立套件,
而不必等待所有相依套件更新,material_ui 與
cupertino_ui 提供了相容性橋接工具。
請在 MaterialApp.builder 中,
使用 MaterialUiCompatibilityBridge 包住你的應用程式:
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(),
);
}
}
橋接的功能與限制
#
MaterialUiCompatibilityBridge 會將主題與在地化資料
向下注入元件樹。
這讓尚未遷移的子元件,以及從 context 讀取設計狀態的相依套件
(例如 Theme.of(context) 或 MaterialLocalizations.of(context))
能繼續正常運作。
不過,當相依套件在其公開 API 簽章中
公開、接受或回傳框架內建的 SDK 型別時
(例如將 FloatingActionButtonLocation、
ColorScheme 或 TextTheme 作為參數或回呼回傳值傳遞),
相容性橋接無法解決型別不符的問題。
由於 Dart 會在不同套件的匯入之間強制執行靜態型別檢查,
來自 package:flutter/material.dart 的值,
無法指派給預期 package:material_ui 型別的參數。
與 API 簽章耦合的相依套件,必須先遷移至獨立套件,
你的應用程式才能將新型別傳遞給它們。
解耦的在地化
#
在這次轉換中,flutter_localizations 已針對設計元件解除捆綁。
Material 與 Cupertino 元件的在地化委派(delegate)與翻譯字串,
現在直接存放於 package:material_ui 與
package:cupertino_ui 中。
遷移前的程式碼:
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// ...
MaterialApp(
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
// ...
);
遷移後的程式碼:
import 'package:material_ui/material_ui.dart';
// ...
MaterialApp(
localizationsDelegates: GlobalMaterialLocalizations.delegates,
// ...
);
將 localizationsDelegates 設為 GlobalMaterialLocalizations.delegates,
會自動一併包含 Cupertino 與 Widgets 的委派,
讓在地化設定更簡單。
給套件作者的指引
#
如果你在 Flutter 生態系中維護開源套件或插件,
遷移至 package:material_ui 或 package:cupertino_ui,
對尚未更新相依套件的使用者來說會是一項破壞性變更。
雖然符號與類別名稱維持不變,
但技術上它們是從一個全新的函式庫中被參照。
請將這次遷移視為你的套件的主要版本升級。
參考資料
#套件文件:
相關 issue:
相關部落格文章與公告:
Unless stated otherwise, the documentation on this site reflects Flutter 3.47. Page last updated on 2026-10-25. View source or report an issue.