pichillilorenzo / flutter_inappwebview

A Flutter plugin that allows you to add an inline webview, to use a headless webview, and to open an in-app browser window.
https://inappwebview.dev
Apache License 2.0
3.32k stars 1.64k forks source link

GestureDetector's onTapDown isn't working as expect with InAppWebView #412

Closed max-yilang closed 4 years ago

max-yilang commented 4 years ago

Environment

Flutter version: v1.17.3 Plugin version: 3.4.0+1 iOS version: 13.5 Xcode version: 11.5 Device information: iPhone 8 Plus

Description

Widget _buildWebView() {
    return GestureDetector(
      onTapDown: (TapDownDetails details) {
        print(details.globalPosition.dx);
      },
      child: InAppWebView(
        initialOptions: InAppWebViewGroupOptions(
          crossPlatform: InAppWebViewOptions(
            javaScriptEnabled: true,
            disableContextMenu: true,
            useShouldOverrideUrlLoading: true
          ),
          ios: IOSInAppWebViewOptions(
            allowsLinkPreview: false,
          ),
        ),
        initialUrl: project.url,
        onWebViewCreated: (InAppWebViewController controller) {
          setState(() => _webController = controller);
        },
      ),
    );
  }

Expected behavior:

GestureDetector onTapDown triggers when you tap on the web page

Current behavior:

GestureDetector onTapDown only trigger if you tap and hold for a short sec

pichillilorenzo commented 4 years ago

GestureDetector.onTapDown as written in the Official API: This is called after a short timeout, even if the winning gesture has not yet been selected.

pichillilorenzo commented 4 years ago

An example using gestureRecognizers:

InAppWebView(
  gestureRecognizers: Set()
    ..add(
        Factory<TapGestureRecognizer>(() => TapGestureRecognizer()
          ..onTapDown = (TapDownDetails details) {
            print(details.globalPosition.dx);
          })),
  initialUrl: "https://flutter.dev/",
  initialOptions: InAppWebViewGroupOptions(
    crossPlatform: InAppWebViewOptions(
        debuggingEnabled: true,
    ),
  ),
  onWebViewCreated: (InAppWebViewController controller) {
    _webViewController = controller;
  },
),
max-yilang commented 4 years ago

GestureDetector.onTapDown as written in the Official API: This is called after a short timeout, even if the winning gesture has not yet been selected.

you need to press down much longer to get the event trigger if it wraps the InAppWebView comparing to a regular Container widget.

max-yilang commented 4 years ago

An example using gestureRecognizers:

InAppWebView(
  gestureRecognizers: Set()
    ..add(
        Factory<TapGestureRecognizer>(() => TapGestureRecognizer()
          ..onTapDown = (TapDownDetails details) {
            print(details.globalPosition.dx);
          })),
  initialUrl: "https://flutter.dev/",
  initialOptions: InAppWebViewGroupOptions(
    crossPlatform: InAppWebViewOptions(
        debuggingEnabled: true,
    ),
  ),
  onWebViewCreated: (InAppWebViewController controller) {
    _webViewController = controller;
  },
),

this doesn't seem to work

pichillilorenzo commented 4 years ago

you need to press down much longer to get the event trigger if it wraps the InAppWebView comparing to a regular Container widget.

Are you using an emulator? I tested it on a real device and it works.

this doesn't seem to work

Could you post full code?

max-yilang commented 4 years ago

Are you using an emulator? I tested it on a real device and it works.

I tried it on both simulator and an iPhone 8 Plus, have to tap and hold for half a sec to trigger the onTapDown event whereas it's almost instant if you wrap a regular container in GestureDetector

Could you post full code?

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: InAppWebView(
gestureRecognizers: Set()
..add(Factory<TapGestureRecognizer>(() => TapGestureRecognizer()
..onTapDown = (TapDownDetails details) {
print(details.globalPosition.dx);
})),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
),
),
initialUrl: 'https://pub.dev/',
),
);
}

This doesn't work at all

max-yilang commented 4 years ago

I tried it on both simulator and an iPhone 8 Plus, have to tap and hold for half a sec to trigger the onTapDown event whereas it's almost instant if you wrap a regular container in GestureDetector

also, this is very inconsistent, sometimes it's instant sometimes you have to tap and hold

pichillilorenzo commented 4 years ago

Ok, so I need to investigate it more! As you can see, InAppWebView Widget is just an AndroidView on Android and an UiKitView on iOS: https://github.com/pichillilorenzo/flutter_inappwebview/blob/master/lib/src/in_app_webview.dart#L288

So, it could be that the problem is related to the Flutter native views in general. Have you encountered this problem with other native widgets? Have you tried it?

Thanks

pichillilorenzo commented 4 years ago

I tested with another Flutter native view widget and it is the same. So I think the problem lies on native views in general.

I have done some tests and it seems that it doesn't call the TapGestureRecognizer.acceptGesture method for some reason. It always cancels the tap event.

Instead, if you use the Listener widget, it seems to work:

Listener(
  onPointerDown: (event) {
    print(event);
  },
  child: InAppWebView(
    initialOptions: InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(
        debuggingEnabled: true,
      ),
    ),
    initialUrl: 'https://pub.dev/',
  ),
),

I get the PointerDownEvent#f7e74(position: Offset(89.6, 444.7)) event instantly.

If you don't want to use the Listener widget, you could implement your custom gesture recognizer class, for example, extending the TapGestureRecognizer class, and pass it to the InAppWebView.gestureRecognizers property.

max-yilang commented 4 years ago

I tested with another Flutter native view widget and it is the same. So I think the problem lies on native views in general.

I have done some tests and it seems that it doesn't call the TapGestureRecognizer.acceptGesture method for some reason. It always cancels the tap event.

Instead, if you use the Listener widget, it seems to work:

Listener(
  onPointerDown: (event) {
    print(event);
  },
  child: InAppWebView(
    initialOptions: InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(
        debuggingEnabled: true,
      ),
    ),
    initialUrl: 'https://pub.dev/',
  ),
),

I get the PointerDownEvent#f7e74(position: Offset(89.6, 444.7)) event instantly.

If you don't want to use the Listener widget, you could implement your custom gesture recognizer class, for example, extending the TapGestureRecognizer class, and pass it to the InAppWebView.gestureRecognizers property.

Thanks, this works!

github-actions[bot] commented 3 weeks ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug and a minimal reproduction of the issue.