<

スクロール可能な AlertDialog (非推奨ではなくなりました)

まとめ

アンAlertDialogオーバーフローしたときに自動的にスクロールするようになりました。

コンテクスト

この変更が行われる前は、 いつAlertDialogウィジェットの内容が高すぎます。 ディスプレイがオーバーフローし、内容が切り取られてしまいました。 その結果、次の問題が発生しました。

  • 切り取られたコンテンツの部分を表示する方法はありませんでした。
  • ほとんどのアラート ダイアログには、コンテンツの下にユーザーに次のことを求めるボタンがあります。 行動。コンテンツが溢れてボタンが見えなくなった場合、 ユーザーはその存在に気づいていない可能性があります。

変更内容の説明

以前のアプローチでは、タイトルとコンテンツがリストされていました。 ウィジェットを連続して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,
        ),
      ),
    ),
    // ...
  ],
);

新しいアプローチでは、両方のウィジェットを 1 つにラップします。SingleChildScrollViewボタンバーの上、 両方のウィジェットを同じスクロール可能な一部にする ダイアログの下部にボタン バーを表示します。

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"
スクロールビューのため、レイアウトが変更される場合があります。
ダイアログがすでにオーバーフローしている場合は、 この変更により問題が修正されます。 このレイアウト変更は予想されています。


入れ子になったSingleChildScrollViewAlertDialog.contentコードに残しておけば正しく動作するはずですが、 ただし、意図しない場合は削除する必要があります。 混乱を招く可能性があります。

移行前のコード:

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 ドキュメント:

  • AlertDialog

関連する問題:

  • 最大アクセシビリティ フォント サイズによるオーバーフロー例外

関連する PR:

  • に更新しますAlertDialog.scrollable
  • スクロール可能を実装する最初の試みAlertDialog
  • スクロール可能を実装するという元の試みを元に戻すAlertDialog