Issue Report: Dialogs Dismissed Prematurely with ensureSemantics
Tags: flutter, firebase, webdev, beginners
Published: 2024-05-24 10:07:03

In this issue report (#149001), reported by user "rkunboxed", a problem in Flutter Web is outlined where dialogs dismiss prematurely when ensureSemantics is included. Clicking inside the dialog causes dismissal, contrary to expected behavior. A workaround is suggested involving the use of a hidden Semantics widget. This issue affects releases 3.22 and 3.23.

[read full article](https://flutters.in/issue-report-dialogs-dismissed-prematurely-with-ensuresemantics/)

Issue Details:

Issue Number: #149001

Reported by: rkunboxed

Date: 11 hours ago

Comments: 2

Description

Dialogs in Flutter Web are dismissed prematurely when ensureSemantics is included. Clicking inside the dialog on whitespace causes dismissal, contrary to expected behavior.

Issue Report: Dialogs Dismissed Prematurely with `ensureSemantics`

Steps to Reproduce

Run the code sample as a Web project in Chrome.

Click on the "Show Dialog" button.

Click anywhere inside the dialog that is not a form field.

Observe the dialog being dismissed.

Expected Results

The dialog should not dismiss when any content inside it is clicked. It should only dismiss if the area outside the content (the barrier) is clicked.

Actual Results

Clicking on whitespace inside the dialog causes it to be dismissed in Web builds. This only occurs in Web builds and only when WidgetsFlutterBinding.ensureInitialized().ensureSemantics(); is included.

Code Sample

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Semantics Issue',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _onPressed() {
    showDialog(
      context: context,
      barrierColor: Colors.grey.shade400,
      builder: (context) {
        return _dialogContent;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _onPressed,
              child: const Text('Show Dialog'),
            )
          ],
        ),
      ),
    );
  }

  Widget get _dialogContent => Center(
        child: Container(
          margin: const EdgeInsets.all(50),
          child: const Material(
            child: SizedBox(
              height: 250,
              width: 250,
              child: Padding(
                padding: EdgeInsets.all(20),
                child: Column(
                  children: [
                    TextField(
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: 'Form field one',
                      ),
                    ),
                    SizedBox(height: 40),
                    TextField(
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: 'Form field two',
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      );
}

Workaround

A workaround is available by wrapping the dialog contents in a Stack and including a hidden Semantics widget inside Positioned.fill().

Widget get _dialogContentHack => Center(
        child: Container(
          margin: const EdgeInsets.all(50),
          child: Material(
            child: SizedBox(
              height: 250,
              width: 250,
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Stack(
                  children: [
                    Positioned.fill(
                      child: Semantics(hidden: true),
                    ),
                    const Column(
                      children: [
                        TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Form field one',
                          ),
                        ),
                        SizedBox(height: 40),
                        TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Form field two',
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

Screenshots or Video

Issue Report: Dialogs Dismissed Prematurely with ensureSemantics
[read full article](https://flutters.in/issue-report-dialogs-dismissed-prematurely-with-ensuresemantics/)

Logs

[Paste your logs here]

Flutter Doctor Output

[✓] Flutter (Channel stable, 3.19.2, on macOS 14.2.1 23C71 darwin-arm64, locale en-US)
    • Flutter version 3.19.2 on channel stable at /Users/rona/Sites/Tools/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 7482962148 (3 months ago), 2024-02-27 16:51:22 -0500
    • Engine revision 04817c99c9
    • Dart version 3.3.0
    • DevTools version 2.31.1

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[!] Xcode - develop for iOS and macOS (Xcode 15.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15E204a
    ✗ Unable to get list of installed Simulator runtimes.
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).

[✓] VS Code (version 1.89.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.88.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 14.2.1 23C71 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 125.0.6422.76

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 3 categories.

Additional Information

Flutter Doctor Output: Provided above.

Workaround: A hacky workaround has been discovered by the author, wrapping the dialog contents in a Stack and including a hidden Semantics widget inside Positioned.fill().

Platform: Web

Found in Releases: 3.22, 3.23

Also read:

[What Lies Ahead for Flutter: Advancements, Innovations, & Beyond](https://flutters.in/what-lies-ahead-for-flutter/)

[NVIDIA Accelerates GPU, CPU, & AI Platform Roadmap: Launching New Chips Every Year](https://flutters.in/nvidia-accelerates-gpu/)

FAQs

What is the issue described in the report?

The issue revolves around dialogs being dismissed prematurely on Flutter Web when ensureSemantics is included. Clicking inside the dialog's whitespace causes dismissal contrary to expected behavior.

How can I reproduce the issue?

To reproduce the issue:

Run the provided code sample as a Web project in Chrome.

Click on the "Show Dialog" button.

Click anywhere inside the dialog that is not a form field.

Observe the dialog being dismissed.

What are the expected results?

The dialog should not dismiss when clicking inside it. It should only dismiss if the area outside the dialog (the barrier) is clicked.
[read full article](https://flutters.in/issue-report-dialogs-dismissed-prematurely-with-ensuresemantics/)

What are the actual results?

Clicking on whitespace inside the dialog causes it to be dismissed in Web builds. This behavior is observed only in Web builds and when WidgetsFlutterBinding.ensureInitialized().ensureSemantics(); is included.

Is there a workaround available?

Yes, a workaround has been discovered by the author. It involves wrapping the dialog contents in a Stack and including a hidden Semantics widget inside Positioned.fill().

How can I implement the workaround?

You can implement the workaround by using the provided _dialogContentHack method in the code sample. This method wraps the dialog contents in a Stack and includes a hidden Semantics widget inside Positioned.fill().

Additional Information

Platform: Web

Found in Releases: 3.22, 3.23
[read full article](https://flutters.in/issue-report-dialogs-dismissed-prematurely-with-ensuresemantics/)