概述

#

现在,当 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