[a11y] TimePicker clock is unnecessarily announced (#175570)

## Description

This PR removes the Semantics for the dial in TimePicker.
This Semantics was meant to announce the input mode (hour or minute) but
this is already done when tapping in the hour or minute fields.

## Related Issue

Fixes [[Google3 Bug]: TimePicker clock is unnecessarily announced to
TalkBack users](https://github.com/flutter/flutter/issues/175369)

## Tests

Updates 1 test.
This commit is contained in:
Bruno Leroux 2025-09-20 08:30:31 +02:00 committed by GitHub
parent 02dcc8f34a
commit ff1fd2aee3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 45 deletions

View File

@ -3039,24 +3039,17 @@ class _TimePickerState extends State<_TimePicker> with RestorationMixin {
final Widget dial = Padding(
padding: dialPadding,
child: Semantics(
label: switch (_hourMinuteMode.value) {
_HourMinuteMode.hour => localizations.timePickerHourModeAnnouncement,
_HourMinuteMode.minute => localizations.timePickerMinuteModeAnnouncement,
},
liveRegion: true,
child: ExcludeSemantics(
child: SizedBox.fromSize(
size: defaultTheme.dialSize,
child: AspectRatio(
aspectRatio: 1,
child: _Dial(
hourMinuteMode: _hourMinuteMode.value,
hourDialType: hourMode,
selectedTime: _selectedTime.value,
onChanged: _handleTimeChanged,
onHourSelected: _handleHourSelected,
),
child: ExcludeSemantics(
child: SizedBox.fromSize(
size: defaultTheme.dialSize,
child: AspectRatio(
aspectRatio: 1,
child: _Dial(
hourMinuteMode: _hourMinuteMode.value,
hourDialType: hourMode,
selectedTime: _selectedTime.value,
onChanged: _handleTimeChanged,
onHourSelected: _handleHourSelected,
),
),
),

View File

@ -2424,41 +2424,24 @@ void main() {
WidgetTester tester,
) async {
final SemanticsTester semantics = SemanticsTester(tester);
await mediaQueryBoilerplate(tester, materialType: MaterialType.material3);
const TimeOfDay time = TimeOfDay(hour: 8, minute: 12);
await mediaQueryBoilerplate(tester, initialTime: time, materialType: MaterialType.material3);
final MaterialLocalizations localizations = MaterialLocalizations.of(
tester.element(find.byType(TimePickerDialog)),
);
final Finder semanticsFinder = find.bySemanticsLabel(
localizations.timePickerHourModeAnnouncement,
);
final SemanticsNode semanticsNode = tester.getSemantics(semanticsFinder);
final String formattedHour = localizations.formatHour(time);
final String formattedMinute = localizations.formatMinute(time);
expect(
semanticsNode.label,
localizations.timePickerHourModeAnnouncement,
reason: 'Label should announce hour mode initially',
find.semantics.byValue('${localizations.timePickerHourModeAnnouncement} $formattedHour'),
findsOne,
);
expect(
semanticsNode.hasFlag(SemanticsFlag.isLiveRegion),
isTrue,
reason: 'Node should be a live region to announce changes',
);
// --- Switch to minute mode ---
final Finder minuteControlInkWell = find.descendant(
of: _minuteControl,
matching: find.byType(InkWell),
);
expect(minuteControlInkWell, findsOneWidget, reason: 'Minute control should exist');
await tester.tap(minuteControlInkWell);
await tester.pumpAndSettle();
// Get the updated node properties
expect(
semanticsNode.label,
localizations.timePickerMinuteModeAnnouncement,
reason: 'Label should announce minute mode after switching',
find.semantics.byValue('${localizations.timePickerMinuteModeAnnouncement} $formattedMinute'),
findsOne,
);
semantics.dispose();