在 11 月 13 日的 FlutterFlightPlans 直播中,Flutter 3.38 如期而至,本次版本主要涉及 Dot shorthands、Web 支援增強、性能改進、問題修復和控件預覽等方面。

在 Dart 3.10 + Flutter 3.38 中開始默認支持 Dot shorthands,通過 Dot shorthands 可以使用簡寫方式省略類型前綴,例如使用 .start 而不是 MainAxisAlignment.start:
// With shorthands
Column(
mainAxisAlignment: .start,
crossAxisAlignment: .center,
children: [ /* ... */ ],
),
// Without shorthands
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [ /* … */ ],
),
類似的還有 .all 而不是 EdgeInsets.all:
Padding(
padding: .all(8.0),
child: Text('Hello world'),
),
詳細可見我們在之前聊過的 《Flutter 合併 'dot-shorthands' 語法糖》。
flutter run 命令現在支持設置 Web 的配置文件,可以在工程根目錄放入 web_dev_config.yaml 來配置 web 主機、端口、證書、headers 等,例如:
server:
host: "0.0.0.0" # 定義綁定地址
port: 8080 # 指定開發伺服器的端口
https:
cert-path: "/path/to/cert.pem" # 您的 TLS 證書的路徑
cert-key-path: "/path/to/key.pem" # TLS 證書密鑰的路徑
通過支持代理 (proxy) 設置,還可以將請求轉發到配置的路徑到另一台伺服器:
server:
proxy:
-
target: "http://localhost:5000/" # 您的後端基礎 URL
prefix: "/users/" # 路徑
-
target: "http://localhost:3000/"
prefix: "/data/"
replace: "/report/" # 重定向 URL 中路徑的替換 (可選)
-
target: "http://localhost:4000/"
prefix: "/products/"
replace: ""
最後 3.38 還增強了 Flutter Web 的 hot reload 並默認開啟,當以 -d web-server 參數運行並在瀏覽器打開時,可以支持多個瀏覽器同時連接 hot reload。
當然,和
-d chrome一樣,您也可以使用--no-web-experimental-hot-reload標誌暫時禁用,不過禁用功能將在將來的版本中刪除。
本次 Framework 調整主要圍繞交互優化相關,比如幫助開發人员可以更精細地控制 UI、導航和平台交互等。
首先是引入了新的 OverlayPortal,允許將子 Widget 渲染在任一 Overlay 上,通過 overlayChildLayoutBuilder 可以更靈活地顯示彈出、對話框、通知等 UI,例如:
class _OverlayPortalExampleState extends State<OverlayPortalExample> {
final OverlayPortalController _controller = OverlayPortalController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('OverlayPortal')),
body: Center(
child: OverlayPortal.overlayChildLayoutBuilder(
controller: _controller,
/// ****可以配置 root****
overlayLocation: OverlayChildLocation.rootOverlay,
child: ElevatedButton(
onPressed: () => _controller.toggle(),
child: const Text('點擊顯示浮層'),
),
overlayChildBuilder: (context, info) {
return Material(
elevation: 4,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Container(
padding: const EdgeInsets.all(12),
child: const Text('這是一個浮層'),
),
);
},
),
),
);
}
}
通過 overlayChildLayoutBuilder 可以拿到主 Widget 的位置信息,可將浮層顯示在任意螢幕位置,比如按鈕下方、螢幕中心、或與滑鼠位置對齊。
接著是在 Android 平台下,使用 MaterialApp 時默認啟用了預測後退路由轉場 (predictive back route transitions),後退手勢時能看到當前界面預覽,此外默認頁面轉換已從 ZoomPageTransitionsBuilder 更新為 FadeForwardsPageTransitionsBuilder。
然後就是久違的 PC 端更新,針對 Windows 桌面開發增強:可訪問已連接顯示器列表,並查詢每個顯示器的解析度、刷新率、物理尺寸等屬性,算是對多窗口模式的增強,例如 PlatformDispatcher.displays 獲取到當前所有顯示器:
void printDisplayInfos() {
final platformDispatcher = WidgetsBinding.instance.platformDispatcher;
final displays = platformDispatcher.displays;
for (final display in displays) {
final id = display.id;
final size = display.size; // Size in logical pixels
final dpr = display.devicePixelRatio;
final refreshRate = display.refreshRate;
}
}
同時,現在如果在 Widget 生命週期回調中發生的錯誤(例如 didUpdateWidget)可以更優雅地處理,防止它們在元素樹中導致級聯故障 (#173148),以前如果開發者在這些回調中拋出了異常(哪怕只是一個小錯誤),整個元素樹可能會進入不一致狀態或直接崩潰。
而現在 Framework 在這些生命週期階段調用時, 將內部異常捕獲包裝在更安全的範圍內,也就是說,如果你的某個子 Widget 在 didUpdateWidget() 拋出錯誤, Flutter 會:
FlutterError.onError);也就是讓錯誤隔離更強,不再因為一個 widget 的生命週期異常破壞整個界面,而 IDE 中仍然能看到詳細的異常棧,從而讓應用的健壯性顯著提升(尤其對熱重載、動態組件更新等場景)。
最後是一些問題修復,例如:
ResizeImage 的 == 和 hashCode 實現不正確的問題,在之前即使兩個 ResizeImage 指向同一底層圖像和相同尺寸, Flutter 也認為它們不相等RSuperellipse,以防止在角半徑大於 Widget 本身 (#172254) 時出現渲染錯誤Intl.Locale Web API 來解析瀏覽器語言,取代了以前的手動實現 (#172964)TextField 互動後,Android 輸入法編輯器 (IME) 可能會陷入過時狀態,導致 IME 錯誤地攔截「Enter」或「Space」鍵按下,從而阻止非文本 Widget (如 複選框 或 單選 按鈕)接收事件,而本次的修復可以確保在文本連接關閉時正確重置 InputMethodManager,清除 IME 的過時狀態,並為用戶還原可預測的硬體鍵盤互動在棄用 MaterialState 的基礎上,3.38 繼續內部遷移到更統一的 WidgetState,這提供了一種更一致的方式來定義控件在不同交互狀態(例如按下、懸停或禁用)中的外觀,並且開發這不需要對現有應用程式碼進行更改。
3.38 開始恰遷移已逐步應用在各種 Widget 及其主題,包括 IconButton、ElevatedButton、Checkbox 和 Switch (#173893),新的 API 還增加了功能和靈活性,例如:
IconButton 現在包括一個 statesController 屬性 (#169821),允許以編程方式控制其視覺狀態
Badge.count 構造函數現在包含一個 maxCount 參數 (#171054),可以限制顯示的計數(例如,顯示「99+」而不是「100」)
為了實現更細粒度的手勢控制,InkWell 現在具有 onLongPressUp 回調 (#173221),可用於觸發僅在用戶抬起手指時才相應完成
Cupertino 也繼續朝著更好的 iOS 保真度邁進, CupertinoSlidingSegmentedControl 添加了 isMomentary 屬性 (#164262)以允許控件觸發而不保留選擇,為了更好地匹配原生 iOS 行為,CupertinoSheet 在完全展開時向上拖動時具有微妙的「拉伸」效果 (#168547)
修復 DropdownMenuFormField 在窗體重置時正確清除其文本字段 (#174937)
更新 SegmentedButton 改進焦點處理 (#173953)並確保其邊框正確反映 Widget 的狀態 (#172754)
滾動 (Scrolling) 和 Sliver 系列控件改進,例如 SliverMainAxisGroup / SliverCrossAxisGroup 在複雜滾動佈局中手勢處理、點擊響應、焦點導航更可靠,例如:
另外還改進了複雜佈局中鍵盤和方向鍵用戶的焦點導航,在具有不同滾動軸的嵌套滾動視圖(例如水平輪播的垂直列表)中,定向焦點導航現在更具可預測性,可防止焦點在部分之間意外跳轉
最後, Material 和 Cupertino 與框架的解耦還在繼續,核心內容就是,解耦後需要作為第一方官方包發布,需要自動化語義化版本管理,避免衝突,支持自定義發布(如跳過特定提交、批量破壞性變更),採用「批量發布」(Batch Release),使用 Cocoon cron job 每週生成合併 PR;開發者通過「commit消息、PR 標籤或獨立 changelog 文件標記變更,首選選項為 PR 獨立 changelog 文件,由 bot 合併等。
另外就是 Widgets 測試不導入 Material/Cupertino;Cupertino 不導入 Material,Material 負責所有多庫導入測試,包括 Cupertino 相容性和自適應等。
以下是一些關於 Material 和 Cupertino 與框架的一些關鍵討論地址:
對於構建複雜應用的開發者,3.38 引入了使用 WidgetsFlutterBinding.instance.ensureSemantics (#174163) 在 iOS 上默認打開輔助功能的功能,調試輔助功能問題現在變得更加容易,因為 debugDumpSemanticsTree 包含額外的文本輸入驗證結果信息,以幫助更快地診斷問題 (#174677)。
為了在基於 sliver 的滾動視圖中實現高級可訪問性,3.38 增加了新的 SliverSemantics (#167300),與現有的 Semantics 非常相似,開發人員可以在 CustomScrollView 中使用 SliverSemantics 使用特定語義信息註釋其 sliver 樹的某些部分,這對於註釋標題、分配語義角色以及為螢幕閱讀器向 sliver 添加描述性標籤特別有用,從而為用戶提供更易於理解和訪問的體驗。
最後,核心 Widget 的可訪問性不斷完善,現在默認情況下可以訪問 CupertinoExpansionTile (#174480),AutoComplete 現在向用戶宣布搜索結果的狀態 (#173480), TimePicker (#170060) 中有更大的觸摸目標,有助於提供更易於訪問的開箱即用體驗。
iOS 平台已經完整支持最新的 iOS 26、Xcode 26、macOS 26,特別是在命令行部署使用 devicectl 替代必須啟動 Xcode App 的流程,現在 Flutter 3.38 可以在大多數情況下僅依賴於 Xcode26 命令行構建工具,更多可見:
雖然官方說完全支持,但是 iOS26 問題還是有的,例如:《來了解一下,為什麼你的 Flutter WebView 在 iOS 26 上有點擊問題?》
另外 Flutter 3.38 包括了對 Apple 強制的 UIScene 生命週期的基本支持,這是繼 Apple 在 WWDC25 上宣布之後的一次關鍵的主動更新:「在 iOS 26 之後的版本中,任何使用最新 SDK 構建的 UIKit 應用都將需要使用 UIScene 生命週期,否則它將不會啟動」。
詳細可見:iOS 26 開始強制 UIScene ,你的 Flutter 插件準備好遷移支持了嗎?,因為適配 UIScene 需要 迁移官方提供了手動遷移和自動遷移的支持,其中自動遷移需要配置
flutter config --enable-uiscene-migration,更多遷移細節可見:docs.flutter.dev/release/bre…
對於 UIScene 支持,更致命的主要還是插件開發者,對於插件作者而言 UIScene 遷移帶來了更大的挑戰:必須確保插件既能在已經遷移到 UIScene 的新應用中正常工作,也要能在尚未遷移的舊應用或舊版 iOS 系統上保持相容,例如:
AppDelegate 移到 SceneDelegate,這樣做會導致它在未遷移的應用中完全失效,因此插件必須能夠同時處理兩種生命週期模型register(with registrar: FlutterPluginRegistrar) 方法中,除了像以前一樣通過 registrar.addApplicationDelegate(self) 註冊 AppDelegate 事件監聽外,還需要調用新的 API 來註冊 SceneDelegate 事件的監聽,Flutter 提供了相應的機制讓插件可以接收到場景生命週期的回調UISceneDelegate 協議中的相關方法,在實現時要設計一種優雅降級的邏輯。例如同時實現 applicationDidEnterBackground 和 sceneDidEnterBackground,當 sceneDidEnterBackground 被調用時,執行相應邏輯並設置一個標誌位,以避免 applicationDidEnterBackground中的邏輯重複執行(如果它也被意外調用的話)UIApplication.shared.keyWindow 或其他與單一窗口相關的廢棄 API 的調用都必須被替換升級到 Flutter 3.38 是滿足 Google Play 16 KB 頁面大小相容性要求的重要準備工作, 因為 3.38 的更改可確保你的應用在高 RAM 設備上正常運行,並提供性能優勢,例如啟動速度提高多達 30%。
Flutter 3.38 將默認的 Android ndkVersion 更新為 NDK r28,這是原生代碼實現 16 KB 支持正確對齊所需的最低要求。
Flutter 3.38 還修復(#173770)了影響 Android 上所有 Flutter 應用的嚴重記憶體洩漏,该问题在 3.29.0 中引入,發生在退出時銷毀 Activity 時出現。
對於 Flutter 3.38 版本,Android 環境目前的推薦配置:
為確保應用在 Flutter 版本之間無縫運行,強烈建議在構建文件中使用 Flutter SDK 提供的 API 級變數:
flutter.compileSdkVersion (API 36)flutter.targetSdkVersion (API 36)flutter.minSdkVersion (API 24) or higherperformance overlay 已經重構,現在提高效率的同時,減少了 Skia 和 Impeller 後端的渲染時間,這意味著可以以更少的開銷獲得更準確的性能數據。
對 Vulkan 和 OpenGL ES 後端的大量修復和改進提高了更廣泛設備上的穩定性和性能,包括更好地處理管道快取 (#176322)、fence waiters (#173085) 和 image layout transitions (#173884)。
另外對於 Web,繼續統一 CanvasKit 和 Skwasm 渲染器的工作,3.38 包括了它們的重大重構,以在兩者之間共享更多代碼,這將在未來帶來更一致的體驗和更快的開發 (#174588)。
Flutter 3.35 引入了 Widget Previews,而 Flutter 3.38 版本對 Widget Previews 進行了重大改進,包括 VSCode 和 Intellij / Android Studio 插件都已更新,初步支持 Widget Previews ,可以直接在 IDE 中查看預覽:

在 IDE 中使用時,默認情況下 Widget Previews 環境配置為根據當前選定的源文件過濾顯示的預覽:

另外,Widget Previews 現在支持淺色和深色模式,以及自定義 IDE 配色方案以匹配開發環境,控件預覽環境中的控件也進行了調整,以使用更少的空間,從而為渲染預覽留出更多空間。

此外,覽註解類不再標記為最終註解,現在可以擴展以創建自定義預覽註解,從而減少常見預覽類型的樣板:

並且新的 MultiPreview 基類允許從單個自定義註解創建多個預覽變體:

Preview 類中的新 group 參數允許對相關預覽進行分組,減少了對 @Preview 註解參數的限制,支持私有常量作為 Preview 註解的參數等。

目前關於預覽還有一些問題,例如 #178317 ,例如 Widget 預覽器可能會在 flutter pub get 後崩潰或停止更新。
其他關於 Tool 更新還有:
首先,3.38 進行了可能影響自定義生成腳本的關鍵生成和工具更改,Flutter SDK 根目錄的 version 文件已被刪除,取而代之的是位於 bin/cache (#172793)中的新 flutter.version.json 文件,此外默認情況下不再生成 AssetManifest.json 文件 (#172594)。
另外還有:
OverlayPortal.targetsRootOverlay 構造函數已被棄用,取而代之的是更靈活的 OverlayPortal( overlayLocation: OverlayChildLocation.rootOverlay )CupertinoDynamicColor 上的幾個屬性(例如 withAlpha 和 withOpacity)現在已棄用,取而代之的是標準 Color 方法本次 3.38 的更新還是挺豐富的,同時也是