概述

#

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