Skip to content

Commit 74ea713

Browse files
authored
Add optional flag to determine assertiveness level in aria announcement for flutter web (#107568)
1 parent e505529 commit 74ea713

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

packages/flutter/lib/src/semantics/semantics_event.dart

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ import 'package:flutter/painting.dart';
88

99
export 'dart:ui' show TextDirection;
1010

11+
/// Determines the assertiveness level of the accessibility announcement.
12+
///
13+
/// It is used by [AnnounceSemanticsEvent] to determine the priority with which
14+
/// assistive technology should treat announcements.
15+
enum Assertiveness {
16+
/// The assistive technology will speak changes whenever the user is idle.
17+
polite,
18+
19+
/// The assistive technology will interrupt any announcement that it is
20+
/// currently making to notify the user about the change.
21+
///
22+
/// It should only be used for time-sensitive/critical notifications.
23+
assertive,
24+
}
25+
1126
/// An event sent by the application to notify interested listeners that
1227
/// something happened to the user interface (e.g. a view scrolled).
1328
///
@@ -71,7 +86,7 @@ abstract class SemanticsEvent {
7186
class AnnounceSemanticsEvent extends SemanticsEvent {
7287

7388
/// Constructs an event that triggers an announcement by the platform.
74-
const AnnounceSemanticsEvent(this.message, this.textDirection)
89+
const AnnounceSemanticsEvent(this.message, this.textDirection, {this.assertiveness = Assertiveness.polite})
7590
: assert(message != null),
7691
assert(textDirection != null),
7792
super('announce');
@@ -86,11 +101,20 @@ class AnnounceSemanticsEvent extends SemanticsEvent {
86101
/// This property must not be null.
87102
final TextDirection textDirection;
88103

104+
/// Determines whether the announcement should interrupt any existing announcement,
105+
/// or queue after it.
106+
///
107+
/// On the web this option uses the aria-live level to set the assertiveness
108+
/// of the announcement. On iOS, Android, Windows, Linux, macOS, and Fuchsia
109+
/// this option currently has no effect.
110+
final Assertiveness assertiveness;
111+
89112
@override
90113
Map<String, dynamic> getDataMap() {
91114
return <String, dynamic>{
92115
'message': message,
93116
'textDirection': textDirection.index,
117+
'assertiveness': assertiveness.index,
94118
};
95119
}
96120
}

packages/flutter/lib/src/semantics/semantics_service.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'dart:ui' show TextDirection;
66

77
import 'package:flutter/services.dart' show SystemChannels;
88

9-
import 'semantics_event.dart' show AnnounceSemanticsEvent, TooltipSemanticsEvent;
9+
import 'semantics_event.dart' show AnnounceSemanticsEvent, Assertiveness, TooltipSemanticsEvent;
1010

1111
export 'dart:ui' show TextDirection;
1212

@@ -29,8 +29,12 @@ class SemanticsService {
2929
///
3030
/// For example a camera application can use this method to make accessibility
3131
/// announcements regarding objects in the viewfinder.
32-
static Future<void> announce(String message, TextDirection textDirection) async {
33-
final AnnounceSemanticsEvent event = AnnounceSemanticsEvent(message, textDirection);
32+
///
33+
/// The assertiveness level of the announcement is determined by [assertiveness].
34+
/// Currently, this is only supported by the web engine and has no effect on
35+
/// other platforms. The default mode is [Assertiveness.polite].
36+
static Future<void> announce(String message, TextDirection textDirection, {Assertiveness assertiveness = Assertiveness.polite}) async {
37+
final AnnounceSemanticsEvent event = AnnounceSemanticsEvent(message, textDirection, assertiveness: assertiveness);
3438
await SystemChannels.accessibility.send(event.toMap());
3539
}
3640

packages/flutter/test/semantics/semantics_service_test.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ void main() {
2020
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, handleMessage);
2121

2222
await SemanticsService.announce('announcement 1', TextDirection.ltr);
23-
await SemanticsService.announce('announcement 2', TextDirection.rtl);
24-
23+
await SemanticsService.announce('announcement 2', TextDirection.rtl, assertiveness: Assertiveness.assertive);
2524
expect(log, equals(<Map<String, dynamic>>[
26-
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 1', 'textDirection': 1}},
27-
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 2', 'textDirection': 0}},
25+
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 1', 'textDirection': 1, 'assertiveness': 0}},
26+
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 2', 'textDirection': 0, 'assertiveness': 1}},
2827
]));
2928
});
3029
}

0 commit comments

Comments
 (0)