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

GestureDetector doesn't receive events when it's child is a ListView or a ScrollView. #72996

Closed
parsa-deriv opened this issue Dec 27, 2020 · 24 comments
Labels
f: gestures flutter/packages/flutter/gestures repository. f: scrolling Viewports, list views, slivers, etc. found in release: 1.22 Found to occur in 1.22 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on r: timeout Issue is closed due to author not providing the requested details in time

Comments

@parsa-deriv
Copy link

Use case

Basically, when you want to receive the gesture events that happen on a widget, you'd wrap that widget inside a GestureDetector.
That works fine, except when that child widget is a ListView or a SingleChildScrollView. In those scenarios, GestureDetector doesn't receive those events and you need to use a Listener widget, which receives low-level gestures and has pretty basic gesture callbacks. And it is a pain to add thresholding deltas to prevent it from detecting taps instead of drag starts.

Proposal

It would be awesome if flutter had this ability to receive gestures when a ListView or a ScrollView is inside a GestureDetector.

@iapicca
Copy link
Contributor

iapicca commented Dec 27, 2020

@parsa-fs
GestureDetector seems to catch the onTap as expected
does the code below represent the issue you are describing?

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: Material(
          child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () => print('gesture detected'),
            child: ListView.builder(
              itemBuilder: (context, _) => const Center(
                child: FlutterLogo(size: 80),
              ),
            ),
          ),
        ),
      ),
    );

@bernaferrari
Copy link
Contributor

I think this is an old duplicated issue which seems like a bug. You should use Listener because yes.

@parsa-deriv
Copy link
Author

@parsa-fs
GestureDetector seems to catch the onTap as expected
does the code below represent the issue you are describing?

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: Material(
          child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () => print('gesture detected'),
            child: ListView.builder(
              itemBuilder: (context, _) => const Center(
                child: FlutterLogo(size: 80),
              ),
            ),
          ),
        ),
      ),
    );

Hey @iapicca ,
Thank you for the reply, yeah onTap works(but sometimes, I don't know why), but my main problem is detecting dragging events, when you have a callback for let's say onVerticalDragUpdate, it doesn't detect the drags.

@darshankawar
Copy link
Member

@parsa-fs
Can you provide a use case with code sample and proposal code sample that would resolve the issue ?
Thanks.

@darshankawar darshankawar added in triage Presently being triaged by the triage team waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds labels Dec 28, 2020
@justinmc
Copy link
Contributor

+1 to a full code sample.

Flutter uses a gesture arena instead of something like event bubbling on the web. It can be tough to listen for the same gesture in two different nested widgets. Here is an example of how we do this for taps in the framework.

@parsa-deriv
Copy link
Author

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.dark(),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  double _bottomSheetHeight = 200;
  final _maxBottomSheetHeight = 300;
  final _minBottomSheetHeight = 200;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Hello"),
      ),
      bottomSheet: GestureDetector(
        onVerticalDragUpdate: (details) {
          setState(() {
            if (details.delta.dy < 0 &&
                (_bottomSheetHeight + details.delta.dy) <=
                    _maxBottomSheetHeight) {
              _bottomSheetHeight -= details.delta.dy;
            } else if (details.delta.dy > 0 &&
                (_bottomSheetHeight - details.delta.dy) >=
                    _minBottomSheetHeight) {
              _bottomSheetHeight -= details.delta.dy;
            }
          });
        },
        child: Container(
          height: _bottomSheetHeight,
          width: double.infinity,
          color: Colors.red,
          child: ListView(
            children: [
              Text("kjds"),
              Text("kjds"),
              Text("kjds"),
              Text("kjds"),
              Text("kjds"),
              Text("kjds"),
              Text("kjds"),
            ],
          ),
        ),
      ),
    );
  }
}

I know that here in this code I can use a DraggableScrollableBottomSheet, but If I have a dynamic child in the outer ListView, and if that child is another ListView which I can't pass it my own controller, it fails to handle the height of the bottom sheet.

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 29, 2020
@darshankawar
Copy link
Member

flutter doctor -v
[✓] Flutter (Channel stable, 1.22.5, on Mac OS X 10.15.4 19E2269 darwin-x64,
    locale en-IN)
    • Flutter version 1.22.5 at /Users/dhs/documents/Fluttersdk/flutter
    • Framework revision 7891006299 (3 weeks ago), 2020-12-10 11:54:40 -0800
    • Engine revision ae90085a84
    • Dart version 2.10.4

 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
    • Android SDK at /Users/dhs/Library/Android/sdk
    • Platform android-30, build-tools 30.0.0
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.0.1, Build version 12A7300
    • CocoaPods version 1.9.3

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)

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

[✓] Connected device (2 available)
    • sdk gphone x86 arm (mobile)         • emulator-5554
      • android-x86 • Android 11 (API 30) (emulator)
    • iPhone SE (2nd generation) (mobile) • 6C85835D-FBFD-4AB3-8DE8-B4FAD35E5367
      • ios         • com.apple.CoreSimulator.SimRuntime.iOS-14-0 (simulator)

! Doctor found issues in 1 category.


@darshankawar darshankawar added f: gestures flutter/packages/flutter/gestures repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. found in release: 1.22 Found to occur in 1.22 has reproducible steps The issue has been confirmed reproducible and is ready to work on passed first triage and removed in triage Presently being triaged by the triage team labels Dec 29, 2020
@parsa-deriv
Copy link
Author

It's interesting too, that the GestureDetector widget inherits from the Listener widget, but it can't receive the drag gestures, though Listener can.

@justinmc
Copy link
Contributor

Could you achieve what you want by listening to scroll changes?

@parsa-deriv
Copy link
Author

parsa-deriv commented Dec 30, 2020

Unfortunately no, because I need to know when the user starts dragging and when it ends.
Basically, I need to listen to onVerticalDragStart, onVerticalDragUpdate, and onVerticalDragEnd, I need those DragUpdateDetails object that those callbacks provide.

@TahaTesser
Copy link
Member

Check #73039

@parsa-deriv
Copy link
Author

As I understood, there aren't many similarities between these two issues. I want to wrap my ListView inside a GestureDetector, but that issue is the opposite.
I wish there was a property for ListView to make it not to prevent the gestures to reach their ancestors.

@parsa-deriv
Copy link
Author

Hey everyone,
Any updates?

@edunatalec
Copy link

Maybe this can help you
https://pub.dev/packages/sliding_up_panel

Try to compare what you need with the package property panelBuilder

@Ruoyu2021
Copy link

Ruoyu2021 commented Aug 10, 2021

FLUTTER在点击事件拦截上有很多问题,谁有解决办法吗?比如#62833 应该也是事件拦截问题。

@Ruoyu2021
Copy link

https://stackoverflow.com/questions/52910339/flutter-gesturedetector-apparently-doesnt-receive-drag-events-when-it-has-a-li
Use Listener instead of GestureDetector, Listener can receive touch event.

@TheOnlyBeardedBeast
Copy link

TheOnlyBeardedBeast commented Sep 10, 2021

I have a similar issue, I would like to achieve a "semantic zoom" effect, I wrapped my scrollView with a GestureDetector, but sometimes it just ignores my pinchzoom, and starts scrolling the scrollview, even if multiple touches are happening. (visible by devtool settings)

@TheOnlyBeardedBeast
Copy link

TheOnlyBeardedBeast commented Sep 13, 2021

Ok so I went through the implementation of the scrollview, it uses a scrollbale, which has a defined RawGestureDetector with Vertical or Horizontal drag gesture, there is a listener in the scrollable, I added a pointer counter by using the Listener onPointer events, in case the number of pointers > 1 I disable the drag gesture recognition and I cancel any running drags, after this a gesture detector works above a custom customScrollview in my case. You have to simply recreated the customScrolview which should use an edited scrollable.

The easiest soulution would be if there would be a single pointer drag gesture, which would not allow scrolling with multiple fingers, and by a simply boolean this behavior could be overwritten.

@1232209
Copy link

1232209 commented Nov 29, 2021

can I get your code,appreciate!

@TheOnlyBeardedBeast
Copy link

@1232209
GestureScrollView.dart and GestureScrollable.dart in this repo https://github.com/TheOnlyBeardedBeast/FlutterWindowsUI lib folder.

@Piinks
Copy link
Contributor

Piinks commented Jun 16, 2022

From the original code sample, this appears to be working as expected, a GestureDetector above a vertical list view will not receive a vertical drag because the ListView claims that gesture. There was a suggestion to listen to scroll notifications - you can listen to the start, update and end of the scrolling with notifications.

@Piinks Piinks added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jun 16, 2022
@github-actions
Copy link

github-actions bot commented Jul 7, 2022

Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now.
If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones.
Thanks for your contribution.

@github-actions github-actions bot closed this as completed Jul 7, 2022
@JaffaKetchup
Copy link

JaffaKetchup commented Jul 20, 2022

Just a note for anyone reading in, 'flutter_map' has also had this problem (see fleaflet/flutter_map#1308).

We are using a Listener, then a PositionedTapDetector2 (which just boils down to a GestureDetector), then a GestureDetector, then the actual map. If the overall widget is placed inside a ListView, only horizontal pan events seem to pass through, although vertical events directly after a horizontal event still seems to work.

However, the weirdest part is, not all devices behave the same way. Specifically, iOS doesn't seem to have an issue, whereas every other platform does.

@darshankawar darshankawar added r: timeout Issue is closed due to author not providing the requested details in time and removed waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds labels Jul 21, 2022
@github-actions
Copy link

github-actions bot commented Aug 4, 2022

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, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
f: gestures flutter/packages/flutter/gestures repository. f: scrolling Viewports, list views, slivers, etc. found in release: 1.22 Found to occur in 1.22 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on r: timeout Issue is closed due to author not providing the requested details in time
Projects
None yet
Development

No branches or pull requests