diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 20616a8ba4..c4abe8fc08 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -526,7 +526,10 @@ class AlertDialog extends StatelessWidget { ), child: DefaultTextStyle( style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subtitle1!, - child: content!, + child: Semantics( + container: true, + child: content!, + ), ), ); } @@ -877,7 +880,11 @@ class SimpleDialog extends StatelessWidget { ), child: DefaultTextStyle( style: titleTextStyle ?? DialogTheme.of(context).titleTextStyle ?? theme.textTheme.headline6!, - child: Semantics(namesRoute: label == null, child: title), + child: Semantics( + namesRoute: label == null, + container: true, + child: title + ), ), ); } diff --git a/packages/flutter/test/material/dialog_test.dart b/packages/flutter/test/material/dialog_test.dart index fd8adb591f..bf09e1d29c 100644 --- a/packages/flutter/test/material/dialog_test.dart +++ b/packages/flutter/test/material/dialog_test.dart @@ -1341,6 +1341,71 @@ void main() { semantics.dispose(); }); + // Regression test for https://github.com/flutter/flutter/issues/78229. + testWidgets('AlertDialog has correct semantics for content in iOS', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData(platform: TargetPlatform.iOS), + home: const AlertDialog( + title: Text('title'), + content: Text('content'), + actions: [ TextButton(onPressed: null, child: Text('action')) ], + ), + ) + ); + + expect(semantics, hasSemantics(TestSemantics.root( + children: [ + TestSemantics( + id: 1, + textDirection: TextDirection.ltr, + children: [ + TestSemantics( + id: 2, + children: [ + TestSemantics( + id: 3, + flags: [SemanticsFlag.scopesRoute], + children: [ + TestSemantics( + id: 4, + children: [ + TestSemantics( + id: 5, + flags: [SemanticsFlag.namesRoute], + label: 'title', + textDirection: TextDirection.ltr, + ), + // The content semantics does not merge into the semantics + // node 4. + TestSemantics( + id: 6, + label: 'content', + textDirection: TextDirection.ltr, + ), + TestSemantics( + id: 7, + flags: [SemanticsFlag.isButton, + SemanticsFlag.hasEnabledState], + label: 'action', + textDirection: TextDirection.ltr, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ], + ), ignoreTransform: true, ignoreId: true, ignoreRect: true)); + + semantics.dispose(); + }); + testWidgets('AlertDialog widget always contains alert route semantics for android', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); @@ -1439,6 +1504,79 @@ void main() { semantics.dispose(); }); + // Regression test for https://github.com/flutter/flutter/issues/78229. + testWidgets('SimpleDialog has correct semantics for title in iOS', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData(platform: TargetPlatform.iOS), + home: const SimpleDialog( + title: Text('title'), + children: [ + Text('content'), + TextButton(onPressed: null, child: Text('action')) + ], + ), + ) + ); + + expect(semantics, hasSemantics(TestSemantics.root( + children: [ + TestSemantics( + id: 1, + textDirection: TextDirection.ltr, + children: [ + TestSemantics( + id: 2, + children: [ + TestSemantics( + id: 3, + flags: [SemanticsFlag.scopesRoute], + children: [ + TestSemantics( + id: 4, + children: [ + // Title semantics does not merge into the semantics + // node 4. + TestSemantics( + id: 5, + flags: [SemanticsFlag.namesRoute], + label: 'title', + textDirection: TextDirection.ltr, + ), + TestSemantics( + id: 6, + flags: [SemanticsFlag.hasImplicitScrolling], + children: [ + TestSemantics( + id: 7, + label: 'content', + textDirection: TextDirection.ltr, + ), + TestSemantics( + id: 8, + flags: [SemanticsFlag.isButton, + SemanticsFlag.hasEnabledState], + label: 'action', + textDirection: TextDirection.ltr, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ], + ), + ], + ), ignoreTransform: true, ignoreId: true, ignoreRect: true)); + + semantics.dispose(); + }); + testWidgets('Dismissible.confirmDismiss defers to an AlertDialog', (WidgetTester tester) async { final GlobalKey _scaffoldKey = GlobalKey(); final List dismissedItems = [];