跳至主要內容

可滾動的 AlertDialog(不再棄用)

摘要

#

AlertDialog 現在會在內容溢出時自動滾動。

背景

#

在此變更之前,當 AlertDialog 元件的內容過高時,顯示會溢出,導致內容被裁剪。這導致了以下問題

  • 沒有辦法查看被裁剪的內容部分。
  • 大多數的警示對話方塊在內容下方都有按鈕,提示使用者採取行動。如果內容溢出,遮蔽了按鈕,使用者可能不會意識到它們的存在。

變更說明

#

先前的做法是將標題和內容元件連續列在 Column 元件中。

dart
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,
        ),
      ),
    ),
    // ...
  ],
);

新的方法是將兩個元件都包裝在按鈕列上方的 SingleChildScrollView 中,使兩個元件成為同一個可滾動的部分,並在對話方塊底部顯示按鈕列。

dart
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,語義測試可能會失敗。

TalkbackVoiceOver 功能的手動測試顯示,它們仍然表現出與之前相同的(正確)行為。

黃金測試可能會失敗。

由於 SingleChildScrollView 現在嵌套了標題和內容元件,此變更可能會導致(先前通過的)黃金測試產生差異。一些 Flutter 專案會透過取得 Flutter 除錯版本中使用的語義節點的黃金測試來建立語義測試。


任何反映滾動容器新增的語義黃金更新都是預期的,這些差異應該可以安全接受。

範例產生的語義樹

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,它應該可以正常運作,但如果不是預期的,則應將其移除,因為這可能會造成混淆。

遷移前的程式碼

dart
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: () {}),
  ],
)

遷移後的程式碼

dart
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