Skip to content

[Web] SemanticsService.sendAnnouncement is not working inside a dialog #179076

@Mickelle

Description

@Mickelle

Steps to reproduce

  1. Open a flutter dialog
  2. On a button click inside the dialog call SemanticsService.sendAnnouncement

Expected results

Screen reader announces the message

Actual results

The message is not announced

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SemanticsBinding.instance.ensureSemantics();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Semantics Announce ',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyWidget(),
    );
  }
}

/// Run this file:
/// flutter run -t lib/main.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  void showAlertDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext dialogContext) {
        return AlertDialog(
          title: const Text('Confirmation'),
          content: const Text('Are you sure you want to proceed?'),
          actions: <Widget>[
            Row(
              children: [
                TextButton(
                  onPressed: () => _announce(dialogContext),
                  child: const Text('Announce'),
                ),
                TextButton(
                  child: const Text('OK'),
                  onPressed: () {
                    Navigator.of(dialogContext).pop();
                  },
                ),
              ],
            ),
          ],
        );
      },
    );
  }

  void showSimpleDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext dialogContext) {
        return SimpleDialog(
          title: const Text('Choose an option'),
          children: <Widget>[
            SimpleDialogOption(
              onPressed: () => _announce(dialogContext),
              child: const Text('Announce'),
            ),
            SimpleDialogOption(
              onPressed: () {
                Navigator.pop(dialogContext, 'Option 2');
              },
              child: const Text('Close'),
            ),
          ],
        );
      },
    );
  }

  void showCustomDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext dialogContext) {
        return Dialog(
          child: Container(
            padding: const EdgeInsets.all(20),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                const Text('This is a custom dialog!'),
                ElevatedButton(
                  onPressed: () => _announce(dialogContext),
                  child: const Text('Announce'),
                ),
                ElevatedButton(
                  onPressed: () {
                    Navigator.of(dialogContext).pop();
                  },
                  child: const Text('Close'),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  void _announce(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await Future.delayed(const Duration(milliseconds: 1000));
      SemanticsService.sendAnnouncement(
        View.of(context),
        'Hello world',
        TextDirection.ltr,
      );
      print('=================== Hello world Announced');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dialog Semantics Announce'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(50),
        child: Column(
          children: [
            ElevatedButton(
              child: const Text('Announce'),
              onPressed: () => _announce(context),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              child: const Text('Alert Dialog'),
              onPressed: () => showAlertDialog(context),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              child: const Text('Simple Dialog'),
              onPressed: () => showSimpleDialog(context),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              child: const Text('Custom Dialog'),
              onPressed: () => showCustomDialog(context),
            ),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
user@mac-macmini test-app % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.38.2, on macOS 15.6 24G84 darwin-arm64, locale en-IN)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
[✓] Chrome - develop for the web
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)found in release: 3.38Found to occur in 3.38found in release: 3.39Found to occur in 3.39has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions