Sitelet https://web.archive.org/web/20210811053429/https://github.com/flutter/flutter/issues/49084
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot detect taps on PlatformViews #49084

Open
hterkelsen opened this issue Jan 17, 2020 · 10 comments
Open

Cannot detect taps on PlatformViews #49084

hterkelsen opened this issue Jan 17, 2020 · 10 comments

Comments

@hterkelsen
Copy link
Contributor

@hterkelsen hterkelsen commented Jan 17, 2020

If you have a GestureDetector parent of a PlatformView, then the onTap of the GestureDetector is not called even when the PlatformView has no gesture detectors. I wrote a test case showing the issue:

    testWidgets('PlatformViewSurface works with GestureDetector parent', (WidgetTester tester) async {
      bool tapAcceptedByParent = false;
      await tester.pumpWidget(
        Align(
          alignment: Alignment.topLeft,
          child: Container(
            margin: const EdgeInsets.all(10.0),
            child: GestureDetector(
              onTap: () {
                tapAcceptedByParent = true;
              },
              child: SizedBox(
                width: 200.0,
                height: 100.0,
                child: PlatformViewSurface(
                  controller: controller,
                  gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
                  hitTestBehavior: PlatformViewHitTestBehavior.opaque),
              ),
            ),
          ),
        ),
      );

      final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
      await gesture.up();

      expect(tapAcceptedByParent, true);
      expect(
        controller.dispatchedPointerEvents,
        isEmpty,
      );
    });

The test case fails both expects.

@amirh suggested changing the GestureDetector's behavior to HitTestBehavior.opaque and the PlatformViewSurface's hitTestBehavior to PlatformViewHitTestBehavior.transparent, which causes the test to pass, but I'm not 100% sure why.

@amirh
Copy link
Contributor

@amirh amirh commented Jan 17, 2020

With the PlatformViewSurface's hitTestBehavior set to transparent, the surface is not hittested and doesn't enter the arena, leaving the tap detector to be the default winner.

@amirh amirh added the plugin label Jan 17, 2020
@amirh
Copy link
Contributor

@amirh amirh commented Jan 17, 2020

The TapGestureRecognizer only accepts gestures as the default winner (when there are no other recognizers the claim the gesture, Dartdoc).

A PlatformViewSurface currently always contributes a member to the arena which prevents the tap detector from winning.

In some sense this is working as intended, as the tap recognizer says "I only recognizer when I know nothing else wants the touches", and a platform view that has non transparent hit test behavior is always "interested" in the touch events.

@hterkelsen can you describe the concrete use case for this?

@hterkelsen
Copy link
Contributor Author

@hterkelsen hterkelsen commented Jan 17, 2020

I'm trying to get the video_player example working for web. Specifically the part where you play/pause by tapping the video: https://github.com/flutter/plugins/blob/master/packages/video_player/video_player/example/lib/main.dart#L65

It works on Android and iOS because the VideoPlayer widget is backed by a Texture widget. On the web it is backed by a HtmlElementView widget which uses PlatformViewLink.

@amirh
Copy link
Contributor

@amirh amirh commented Jan 17, 2020

Does the video player HtmlElementView need to block any touch events from being used by the framework? if not would it make sense to set the hit testing behavior to transparent?

@hterkelsen
Copy link
Contributor Author

@hterkelsen hterkelsen commented Jan 17, 2020

I guess not. Unfortunately I hard-coded PlatformViewHitTestBehavitor.opaque and an empty gesture recognizer set for HtmlElementView since we are unable to fully support forwarding pointers to HTML elements (if they are cross-origin <iframe>s).

I am going to write a PR that adds better gesture support for HtmlElementView so that users can set the hit test behavior and recognizers and so that we forward pointer events to the element (which will just be ignored if it's a cross-origin <iframe>, but should work for things like video players).

@hterkelsen
Copy link
Contributor Author

@hterkelsen hterkelsen commented Jan 17, 2020

This may just be my lack of familiarity with the gesture system but this behavior is still surprising to me, especially since the test case above would pass if instead of onTap it was onVerticalDrag or a different gesture type.

It was my assumption that the PlatformViewSurface would only forward pointer events to the underlying platform view if one of its gesture recognizers matched the gesture.

@deakjahn
Copy link

@deakjahn deakjahn commented Apr 2, 2020

@amirh By use case, you mean the general desirability of catching the tap over a PlatformView? If so, by all means. I have a PlatformView that implements some shader operations that Google, for some reason, decided to remove from Skia about two years ago (I tried to convince them not to do it but I failed). But, apart from that, I need to treat them just as any other image in Flutter, including the user tapping on it to start something.

@jameswasher
Copy link

@jameswasher jameswasher commented Sep 15, 2020

Any updates on this?

@vishna
Copy link

@vishna vishna commented Oct 16, 2020

So I've run into this problem while trying to display SVG icons on web - found a workaround for my use case (which was simply registering onTap listener):

  1. Wrap HtmlElementView with IgnorePointer
  2. Add behavior: HitTestBehavior.opaque to GestureTapDetector

Hope this helps some people

@dannnnthemannnn
Copy link

@dannnnthemannnn dannnnthemannnn commented Nov 18, 2020 •

Hi @vishna, can you include a code sample of what your workaround was? I've tried to replicate it but have been unsuccessful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants