可滾動的 AlertDialog(不再被棄用)
AlertDialog 在內容溢出時應自動滾動。
摘要
#當 AlertDialog 內容溢出時,現在會自動啟用滾動。
背景說明
#
在此變更之前,
當 AlertDialog 元件 (Widget) 的內容過高時,
畫面會發生溢位,導致內容被截斷。
這會造成以下問題:
- 被截斷的內容無法檢視。
- 大多數提示對話框(alert dialogs)會在內容下方放置按鈕,讓使用者進行操作。如果內容溢出而遮蔽按鈕,使用者可能不會發現這些按鈕的存在。
變更說明
#先前的做法是將標題和內容元件(Widgets)依序放在 Column 元件中。
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (title != null)
Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24, 24, 24, content == null ? 20 : 0),
child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(
child: title,
namesRoute: true,
container: true,
),
),
),
if (content != null)
Flexible(
child: Padding(
padding: contentPadding,
child: DefaultTextStyle(
style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subhead,
child: content,
),
),
),
// ...
],
);
新的做法會將這兩個元件(Widgets)包裹在 SingleChildScrollView 中,並放置於按鈕區塊(button bar)之上,使這兩個元件成為同一個可滾動區域的一部分,並將按鈕區塊顯示在對話框的底部。
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (title != null || content != null)
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (title != null)
titleWidget,
if (content != null)
contentWidget,
],
),
),
// ...
],
),
遷移指南
#由於此變更,你可能會遇到以下問題:
- 由於新增了
SingleChildScrollView,語意測試(semantics tests)可能會失敗。 -
對
Talkback與VoiceOver功能進行手動測試, 顯示它們仍然維持與先前相同(正確)的行為。 - Golden tests 可能會失敗。
-
此變更可能導致(先前通過的)golden tests 出現差異, 因為
SingleChildScrollView現在同時巢狀了標題與內容元件(Widgets)。 有些 Flutter 專案會透過擷取 Flutter 除錯版本中語意節點的 golden,來建立語意測試。
任何反映滾動容器新增的語意 golden 更新都是預期中的,這些差異可以安全接受。範例產生的 Semantics 樹如下:
flutter: ├─SemanticsNode#30 <-- SingleChildScrollView
flutter: │ flags: hasImplicitScrolling
flutter: │ scrollExtentMin: 0.0
flutter: │ scrollPosition: 0.0
flutter: │ scrollExtentMax: 0.0
flutter: │
flutter: ├─SemanticsNode#31 <-- title
flutter: │ flags: namesRoute
flutter: │ label: "Hello"
flutter: │
flutter: └─SemanticsNode#32 <-- contents
flutter: label: "Huge content"
- 由於加入滾動視圖,可能會導致版面配置變化。
-
如果對話框原本就已經溢出, 這項變更將修正該問題。 這種版面配置的變化是預期中的。
如果在AlertDialog.content中巢狀使用SingleChildScrollView, 只要保留在程式碼中應該可以正常運作, 但如果不是有意為之,建議移除, 以免造成混淆。
遷移前的程式碼:
AlertDialog(
title: Text(
'Very, very large title that is also scrollable',
textScaleFactor: 5,
),
content: SingleChildScrollView( // won't be scrollable
child: Text('Scrollable content', textScaleFactor: 5),
),
actions: <Widget>[
TextButton(child: Text('Button 1'), onPressed: () {}),
TextButton(child: Text('Button 2'), onPressed: () {}),
],
)
遷移後的程式碼:
AlertDialog(
title: Text('Very, very large title', textScaleFactor: 5),
content: Text('Very, very large content', textScaleFactor: 5),
actions: <Widget>[
TextButton(child: Text('Button 1'), onPressed: () {}),
TextButton(child: Text('Button 2'), onPressed: () {}),
],
)
時程
#
合併於版本:1.16.3
穩定版釋出:1.17
參考資料
#設計文件:
API 文件:
相關議題:
相關 PR:
Unless stated otherwise, the documentation on this site reflects Flutter 3.44.0. Page last updated on 2026-06-14. View source or report an issue.