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

[BUG] tap action is hard to invoke by finger #293

Closed
Aoi-hosizora opened this issue Jun 24, 2020 · 37 comments
Closed

[BUG] tap action is hard to invoke by finger #293

Aoi-hosizora opened this issue Jun 24, 2020 · 37 comments
Labels
bug Something isn't working Gallery P1
Projects

Comments

@Aoi-hosizora
Copy link

Aoi-hosizora commented Jun 24, 2020

Versions
Flutter: 1.19.0-2.0.pre.83
Android 8
photo_view: ^0.9.2

Describe the bug

I used PhotoViewGallery.builder to show a set of images. But when I use finger to swipe or click, it is hard to invoke the action. Only by my little finger, will it be invoked sometimes.

For example, onTapDown, onTapUp or double click to zoom.
When I debug in emulator by mouse and use mouse in my Android mobile phone, it works normally. But it is too hard by finger.

But if I use PhotoViewGestureDetector directly, everything works normally.

To Reproduce

Here is my code:

Container(
  decoration: BoxDecoration(color: Colors.black),
  constraints: BoxConstraints.expand(
    height: MediaQuery.of(context).size.height,
  ),
  child: Stack(
    children: [
      Positioned.fill(
        child: PhotoViewGallery.builder(
          scrollPhysics: const BouncingScrollPhysics(),
          backgroundDecoration: BoxDecoration(color: Colors.black),
          loadingBuilder: (c, ImageChunkEvent e) => ImageLoadingView(title: '${_currentPage + 1}', event: e),
          loadFailedChild: ImageLoadFailedView(title: '${_currentPage + 1}'),
          onPageChanged: _onPageChanged,
          pageController: _controller,
          itemCount: widget.images.length,
          builder: (BuildContext context, int index) => PhotoViewGalleryPageOptions(
            initialScale: PhotoViewComputedScale.contained,
            minScale: PhotoViewComputedScale.contained / 2,
            maxScale: PhotoViewComputedScale.covered * 2,
            filterQuality: FilterQuality.high,
            onTapDown: (c, d, v) => _onPointerDown(d.globalPosition),
            onTapUp: _onImagePointerUp,
            heroAttributes: PhotoViewHeroAttributes(
              tag: '${widget.images[index]}: $index',
            ),
            imageProvider: LocalOrNetworkImageProvider(
              url: widget.images[index],
              file: () async => _presenter.getFile(index: index),
            ),
          ),
        ),
      ),
      Positioned(
        bottom: 0,
        child: Listener(...),
      ),
    ),
  ),
)


double _pointerDownXPosition = 0;
double _pointerDownYPosition = 0;

void _onPointerDown(Offset pos) {
  _pointerDownXPosition = pos?.dx ?? 0;
  _pointerDownYPosition = pos?.dy ?? 0;
}

void _onImagePointerUp(BuildContext c, TapUpDetails d, PhotoViewControllerValue v) {
  var width = MediaQuery.of(context).size.width;
  var height = MediaQuery.of(context).size.height;
  Fluttertoast.showToast(
    msg: 'localPosition: ${d.localPosition}, globalPosition: ${d.globalPosition}, ' +
        'x: ${d.globalPosition?.dx}, y: ${d.globalPosition?.dy}, width: $width, height: $height',
  );
}

Screenshots

Emulator:

image

Android by mouse:

image

Android by finger: (I can't capture it)

@Aoi-hosizora Aoi-hosizora added the bug Something isn't working label Jun 24, 2020
@zencubic
Copy link

I've got a similar issue where it is also sometimes hard to swipe to the next image. But I also can relate to the onTap issue. Zooming with 2 fingers works, but double tapping to zoom almost never.

@woodstream
Copy link

@Aoi-hosizora How to use PhotoViewGestureDetector?

@Aoi-hosizora
Copy link
Author

@woodstream You can see the source code in https://github.com/renancaraujo/photo_view/blob/master/lib/src/core/photo_view_core.dart and https://github.com/renancaraujo/photo_view/blob/master/lib/src/core/photo_view_gesture_detector.dart.

PhotoViewGallery -> PhotoView -> PhotoViewCore -> PhotoViewGestureDetector

return PhotoViewGestureDetector(
  child: Container(
    constraints: widget.tightMode ? BoxConstraints.tight(scaleBoundaries.childSize * scale) : null,
    child: Center(
      child: Transform(
        child: customChildLayout,
        transform: matrix,
        alignment: basePosition,
      ),
    ),
    decoration: widget.backgroundDecoration ?? _defaultDecoration,
  ),
  onDoubleTap: nextScaleState,
  onScaleStart: onScaleStart,
  onScaleUpdate: onScaleUpdate,
  onScaleEnd: onScaleEnd,
  hitDetector: this,
  onTapUp: widget.onTapUp == null ? null : onTapUp,
  onTapDown: widget.onTapDown == null ? null : onTapDown,
);

@zencubic
Copy link

@renancaraujo Have you seen this issue? This is a major blocker for my app. It would be very kind of you if you could look at this.

@febryardiansyah
Copy link

@Aoi-hosizora i have same issue here, could you give me simple sample code use PhotoViewGestureDetector ?

@renancaraujo
Copy link
Member

renancaraujo commented Aug 11, 2020

This gallery issue is very very challenging. I can not reproduce it in any of my devices, but there is enough amount of people complaining about this.

Since I'm alone maintaining this lib, I guess I will have to try to fix it even without knowing the reason why.

@gamestap99
Copy link

I believe you can do it

@Aoi-hosizora
Copy link
Author

Aoi-hosizora commented Aug 12, 2020

@febryardiansyah Oh I'm sorry to reply so late, you can see #293 (comment) and ignore some parameters directly.

@renancaraujo
Copy link
Member

renancaraujo commented Aug 12, 2020

Just realized we have a small fix on gesture detector that was not yet released in any version. Would any of you (that can reproduce the bug) test if it works when pointing to photo_view's master?

The fix:
#266

@WeaponMan
Copy link

WeaponMan commented Aug 12, 2020

@renancaraujo I tried master yesterday behaves the same, I have problem with swiping + the double tap, sometimes the picture get "stuck" instead of moving to another picture bcs the custom gesture detector acepted the first event move even there is no way to pan the picture (meaning the picture is not zoomed just diplayed with 0.9 inital scale)

@renancaraujo renancaraujo added this to Todo in Bug solving via automation Aug 13, 2020
@zencubic
Copy link

I can sadly confirm that the latest version does not resolve the error

@renancaraujo
Copy link
Member

I will probably change my career after fixing this. Become an astronaut or something.

@woodstream
Copy link

@renancaraujo As you see, Mars is waiting for you.

@TheLiyo
Copy link

TheLiyo commented Aug 20, 2020

@renancaraujo I think this is not really a good solution, but it basically solved my problem

class PhotoViewGestureRecognizer extends ScaleGestureRecognizer {
  PhotoViewGestureRecognizer({
    this.hitDetector,
    Object debugOwner,
    this.validateAxis,
    PointerDeviceKind kind,
  }) : super(debugOwner: debugOwner, kind: kind);
  final HitCornersDetector hitDetector;
  final Axis validateAxis;

  Map<int, Offset> _pointerLocations = <int, Offset>{};

  Offset _initialFocalPoint;
  Offset _currentFocalPoint;

  Offset _tabDown;

  bool ready = true;

  @override
  void addAllowedPointer(PointerEvent event) {
    if (ready) {
      ready = false;
      _pointerLocations = <int, Offset>{};
    }
    super.addAllowedPointer(event);
  }

  @override
  void didStopTrackingLastPointer(int pointer) {
    ready = true;
    super.didStopTrackingLastPointer(pointer);
  }

  @override
  void handleEvent(PointerEvent event) {
    if (validateAxis != null) {
      _computeEvent(event);
      _updateDistances();
      _decideIfWeAcceptEvent(event);
    }
    super.handleEvent(event);
  }

  void _computeEvent(PointerEvent event) {
    if (event is PointerMoveEvent) {
      if (!event.synthesized) {
        _pointerLocations[event.pointer] = event.position;
      }
    } else if (event is PointerDownEvent) {
      _pointerLocations[event.pointer] = event.position;
    } else if (event is PointerUpEvent || event is PointerCancelEvent) {
      _pointerLocations.remove(event.pointer);
    }

    _initialFocalPoint = _currentFocalPoint;
  }

  void _updateDistances() {
    final int count = _pointerLocations.keys.length;
    Offset focalPoint = Offset.zero;
    for (int pointer in _pointerLocations.keys)
      focalPoint += _pointerLocations[pointer];
    _currentFocalPoint =
        count > 0 ? focalPoint / count.toDouble() : Offset.zero;
  }

  void _decideIfWeAcceptEvent(PointerEvent event) {
    if (!(event is PointerMoveEvent)) {
      if (event is PointerDownEvent) _tabDown = event.position;
      return;
    } else {
      if (_tabDown == event.position) return;
    }
    final move = _initialFocalPoint - _currentFocalPoint;
    final bool shouldMove = validateAxis == Axis.vertical
        ? hitDetector.shouldMoveY(move)
        : hitDetector.shouldMoveX(move);
    if (shouldMove || _pointerLocations.keys.length > 1) {
      acceptGesture(event.pointer);
    }
  }
}

@vikeychen
Copy link

#318 I tested it can work

@DNetORM
Copy link

DNetORM commented Aug 23, 2020

Has this problem been fixed? @renancaraujo give you a suggestion. You can try to ask Google's flutter development engineer to help you find out the problem.

@DNetORM
Copy link

DNetORM commented Aug 23, 2020

@TheLiyo With your code, it seems to solve the problem,I just did a test,But I also hope author can find out the reason and tell us why

@deckerst
Copy link

I'm not sure it's helping this specific issue, but just in case...

A while ago I noticed some precision issue in the HitCornersDetector and I fixed it in my fork: https://github.com/deckerst/photo_view/commit/e1c14b07a1c759c14fa33b066dd240d47812038d

The issue was preventing user interaction for specific combinations of image size and scale (so, screen size). Maybe that's why the issue can be reproduced on some devices but not others... Hopefully you just have to play with precisionErrorTolerance to solve this.

@renancaraujo
Copy link
Member

I've just spent the whole weekend over this. Basically, we have two issues with our custom scale recog: it is taking precedence over all other recognizers even when it shouldn't be doing that, this causes double and taps not to work well. The second issue is that HitCornersDetector has some bugs. The last one is the one that concerns this issue.

@DNetORM @vikeychen and @TheLiyo: I think we can solve that by fixing hit corners instead. This PR should fix this issue, can you test it?

@deckerst That's new to me, but I think we have to add that to different places as well. I shall debug that in more depth. Thanks for the insight. This will help to solve #304

@renancaraujo
Copy link
Member

Anyway, @deckerst would open a PR with this fix?

@renancaraujo renancaraujo moved this from Todo to In progress in Bug solving Aug 24, 2020
@progid
Copy link

progid commented Aug 28, 2020

The problem still here.

@renancaraujo
Copy link
Member

renancaraujo commented Aug 28, 2020

@progid Have you tested with the master branch?

@progid
Copy link

progid commented Sep 1, 2020

@renancaraujo yes, I have. It happens after loadingBuilder is shown.

@leonardocustodio
Copy link

Was this issue fixed? Got kind of confused over here.

@tangjingyuan
Copy link

tangjingyuan commented Sep 10, 2020

#326 should fixed it.

You can try to ref the lib in your pubspec.yaml as the following code:

  photo_view:
    git:
      url: https://github.com/fireslime/photo_view.git
      ref: master

@vadrian89
Copy link

#326 should fixed it.

You can try to ref the lib in your pubspec.yaml as the following code:

  photo_view:
    git:
      url: https://github.com/fireslime/photo_view.git
      ref: master

It seems this worked for me.
Thank you!

@leonardocustodio
Copy link

Yep, working fine, thanks a lot.

@mx1up
Copy link

mx1up commented Sep 15, 2020

double tap and swiping works again, you rock @renancaraujo !

@lucien144
Copy link

Amazing. Installing just the version v0.10.2 didn't work but installing it from the master branch actually helped. Thanks.

@ewolution94
Copy link

Thank you so much! Referencing the lib also worked for me.

@renancaraujo
Copy link
Member

Next release should come ASAP, sorry for the delay.

@clragon
Copy link

clragon commented Oct 4, 2020

I still seem to be having issues with this.
The first double tap works 100%, the second one sometimes,
and the third one to unzoom is in most cases almost impossible to trigger.
Most of the taps just trigger a pan gesture, but it is way too easy to trigger it.
I installed from master so I have the latest code.

@deckerst
Copy link

deckerst commented Oct 5, 2020

@clragon isn't it #216?

@renancaraujo
Copy link
Member

0.10.3 released, this should be fixed.

@renancaraujo
Copy link
Member

renancaraujo commented Nov 15, 2020

I shall close this for now, if someone finds an issue in this matter after updating to 0.10.3, feel free to retake the discussion or message me on discord and I will attack this asap. I hate this bug.

@foreverGoUp
Copy link

foreverGoUp commented Dec 1, 2020

I had confused with the slide problem,but finally i try comment the backgroundDecoration attr and it reslove this problem.Here is my code.hope help you and everyone. @renancaraujo

PhotoViewGallery.builder(
              scrollPhysics: const BouncingScrollPhysics(),
              builder: (BuildContext context, int index) {
                print("-----------index=$index");
                return PhotoViewGalleryPageOptions(
                  imageProvider: NetworkImage(widget.galleryItems[index]),
                  initialScale: PhotoViewComputedScale.contained * 1,
//            heroAttributes: PhotoViewHeroAttributes(
//                tag: widget.galleryItems[index].hashCode),
                );
              },
              pageController: PageController(initialPage: widget.initialIndex),
              itemCount: widget.galleryItems.length,
              loadingBuilder: (context, event) => Center(
                child: Container(
                  width: 20.0,
                  height: 20.0,
                  child: CircularProgressIndicator(
                    value: event == null
                        ? 0
                        : event.cumulativeBytesLoaded / event.expectedTotalBytes,
                  ),
                ),
              ),
              onPageChanged: _onPageChanged,
//        backgroundDecoration: BoxDecoration(color: Colors.black),//加上该行会导致滑动翻页不灵敏
            ),

@andreystavitsky
Copy link

Unfortunately I have same problem on 0.10.3 with Samsung Galaxy s20+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Gallery P1
Projects
Bug solving
  
Done
Development

No branches or pull requests