flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.07k stars 27.21k forks source link

GestureDetector responses wrong x value of location of pan closure in vertical scroll view #49160

Closed guolingege closed 4 years ago

guolingege commented 4 years ago

First of all, my English is poor. So it is hard for me to describe the abstract problem. I will try my best to describe it:

GestureDetector responses wrong x value of location of pan closure in vertical scroll view!

I wrote a custom painter which contains GestureDetector, and listen to it's onPanStart, onPanUpdate and onPanEnd closures. But I got wrong x values both in the closure param DragStartDetails's properties localPosition and globalPosition. They deflect about 40 both in the left and right sids.

The point is, the GestureDetector works correctly in static view such as Container and works incorrectly in vertical scroll views such as SingleChildScrollView and CustomScrollView.

I can record screen to a video to provide further informations. Waiting online!

VladyslavBondarenko commented 4 years ago

Hi @guolingege Could you please provide your flutter doctor -v together with a minimal code sample to reproduce the problem thank you

guolingege commented 4 years ago

Hi @guolingege Could you please provide your flutter doctor -v together with a minimal code sample to reproduce the problem thank you

flutter doctor -v:

MikedeMacBook-Pro:aic_flutter mike$ flutter doctor -v
[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Mac OS X 10.15.2 19C57, locale zh-Hans-CN)
    • Flutter version 1.12.13+hotfix.5 at /Users/mike/flutter
    • Framework revision 27321ebbad (6 weeks ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /Users/mike/AndroidSDK
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • ANDROID_HOME = /Users/mike/AndroidSDK
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.2.1, Build version 11B53
    • CocoaPods version 1.8.4

[✓] Android Studio (version 3.5)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 42.1.1
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (1 available)
    • 公司的iPhone X • d6b7672e123c8b580fa9e7ba2a27799458cbe0ff • ios • iOS 13.2.3

• No issues found!

sample codes:

scroll view - CropPage:

Widget _verticalScrollView(int page) {
    final children = <Widget>[
      _listTile(page, 0, 0),
      .......
    ];
    return CustomScrollView(
      scrollDirection: Axis.vertical,
      slivers: children.myMap((child) {
        return SliverToBoxAdapter(child: child);
      })
    );
  }

Widget _listTile(int page, int section, int row) {
    if (section == 0) {
      if (row == 0) {
        return _cropView(page);
      } else .........
  }

Widget _cropView(int page) {
    SingleTagItem item = _items[page];
    _imageSize = Size(.....
    return CropView.network(
      item.picUrl ?? '',
      padding: EdgeInsets.all(15),
      size: _cropperSize,
      didEndCrop: (ui.Image image, File file, Rect croppedRect) {
        print('didEndCrop setState croppedRect:$croppedRect');
        _croppedRect = croppedRect;
        setState(() {
          _croppedImage = image;
        });
      },
    );
  }

crop view - CropViewState:

@override
  Widget build(BuildContext context) {
    if (!didEditCropRect && widget.defaultCropRect == null) {widget.defaultCropRect:${widget.defaultCropRect}');
      _initCropRect();
    }
    return GestureDetector(
      key: _surfaceKey,
      behavior: HitTestBehavior.opaque,
      onPanStart: _isEnabled ? _handlePanStart : null,
      onPanUpdate: _isEnabled ? _handlePanUpdate : null,
      onPanEnd: _isEnabled ? _handlePanEnd : null,
      child: Container(
        width: widget.size.width,
        height: widget.size.height,
        child: CustomPaint(
          painter: _CropPainter(
              image: _image, area: _currentCropRect, padding: widget.padding),
        ),
      ),
    );
  }

  void _handlePanStart(DragStartDetails details) {
    print('_hitCropHandle localPosition:${details.localPosition}'); ///here prints wrong x value
    print('_hitCropHandle globalPosition:${details.globalPosition}'); ///here prints wrong x value too
    print('_hitCropHandle _currentCropRect:$_currentCropRect');

    _handle = _hitCropHandle(details.localPosition);

    didEditCropRect = true;
  }

IMG_AD6549FB51D1-1

guolingege commented 4 years ago

@VladyslavBondarenko Excuse me, is this issue confirmed?

VladyslavBondarenko commented 4 years ago

Hi @guolingege Yes, I see what you mean. I found that it's easier to write code anew instead of trying to do something with your's.

My code reproducing the issue ``` import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( // body: Container( // child: GestureDetector( // onPanStart: (details) => print('start: ${details.localPosition}'), // onPanDown: (details) => print('down: ${details.localPosition}'), // child: Image( // image: NetworkImage( // 'https://www.w3schools.com/w3css/img_lights.jpg'), // ), // ), // ), body: CustomScrollView( slivers: [ SliverList( delegate: SliverChildListDelegate( [ GestureDetector( onPanStart: (details) => print('start: ${details.localPosition}'), onPanDown: (details) => print('down: ${details.localPosition}'), child: Image( image: NetworkImage( 'https://www.w3schools.com/w3css/img_lights.jpg'), ), ), ], ), ), ], ), ); } } ```

Indeed x value of onPanDown is different from onPanStart when using CustomScrollView, while this is not so when using Container

guolingege commented 4 years ago

Hi @guolingege Yes, I see what you mean. I found that it's easier to write code anew instead of trying to do something with your's.

My code reproducing the issue Indeed x value of onPanDown is different from onPanStart when using CustomScrollView, while this is not so when using Container

You are great! I replaced onPanStart with onPanDown and resolved it.

tag: The onPanStart will be called delayed after onPanDown or even will not be called when the GestureDetector is on a scrollable scroll view, I guess the underlying code needs judge which gesture/gestures should work.

github-actions[bot] commented 3 years 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, including the output of flutter doctor -v and a minimal reproduction of the issue.