How to prevent tap on AlertDialog area from passing behind?

126 views Asked by At

I am using a WebView to show an embedded youtube video.

After that I show an AlertDialog that appears over that WebView and if I tap on the AlertDialog area, the behind video will handle the tap events, such as playing, pausing, etc.

How can I prevent the tap on AlertDialog area from passing behind?

Next you can see an image of that sample App and its source code. There is a floating button that launches the AlertDialog with the text "Ola Mundo". Then taping on the area of the AlertDialog will make the video start playing.

import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class _MyHomePageState extends State<MyHomePage> {
  late double screenWidth;
  late double screenHeight;

  // Get the proportionate height as per screen size
  double getProportionateScreenHeight(double inputHeight) {
    // 812 is the layout height that designer use
    return (inputHeight / 812.0) * screenHeight;
  }

// Get the proportionate height as per screen size
  double getProportionateScreenWidth(double inputWidth) {
    // 375 is the layout width that designer use
    return (inputWidth / 375.0) * screenWidth;
  }

  Uri getYoutubeUrl(BuildContext ctx, id) {
    return Uri.dataFromString(
        '<iframe width="100%" height="${getProportionateScreenWidth(screenHeight)}"'
        ' src="https://www.youtube.com/embed/$id"'
        ' title="YouTube video player" frameborder="0" autoplay;"'
        ' allowfullscreen></iframe>',
        mimeType: 'text/html');
  }

  @override
  Widget build(BuildContext context) {
    final mediaQueryData = MediaQuery.of(context);
    screenWidth = mediaQueryData.size.width;
    screenHeight = mediaQueryData.size.height;

    return Scaffold(
      appBar: AppBar(title: const Text("Sample video")),
      body: SingleChildScrollView(
        child: SizedBox(
          width: MediaQuery.of(context).size.width,
          height: getProportionateScreenHeight(screenWidth),
          child: WebViewWidget(
              controller: WebViewController()
                ..setJavaScriptMode(JavaScriptMode.unrestricted)
                ..setBackgroundColor(Colors.black)
                ..loadRequest(getYoutubeUrl(context, "HF05SHKi55g"))),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showDialog(
              context: context,
              builder: (ctx) => const AlertDialog(
                    content: Text("Ola Mundo"),
                  ));
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}


Updated on 2023-03-01

Related to Flutter Issue PlatformView should support IgnorePointer widget on iOS

1

There are 1 answers

0
Miguel Gamboa On

Since it is still pending a solution for this Issue PlatformView should support IgnorePointer widget on iOS here it is my workaround in the meanwhile.

I start by displaying a video thumbnail (a Stack with the video image and a play button image) rather than the WebView, and after first tap, then I will replace it with the WebView with the embed youtube. Hence, the tap over the alert dialog is not handled by thumbnail and does not play the video.

The skeleton for this code is something like:

Widget _buildVideoSection() {
  return _videoInitialized
    ? _buildWebViewForYoutubeVideo()
    : _buildVideoThumbnail();
}
GestureDetector _buildVideoThumbnail() {
  return GestureDetector(
    onTap: () {
      if (!_videoInitialized) {           
        setState(() => _videoInitialized = true);
      }
    },
    child:Stack(
      children: [
        SizedBox( /*... video image...*/ ),
        SizedBox( /**... play-button.png ...*/),
      ]
    ),
  );
}