Search code examples
androidflutterdartzooming

Flutter: enable image zoom in/out on double tap using InteractiveViewer


I want to enable zoom in and out on double tap of the image, together with scaling in/out on pinch. I saw some tutorials on YouTube where they implemented this feature using GestureDetector like this one but for some reason, it didn't work out for me. In order to implement scaling in/out on pinch, I relied on this answer, and it really works well, but I also want to enable zoom in/out on double tapping the image. Looking up a way to do so on the internet, unfortunately, yielded nothing.

Is there any way to enable zoom in/out with both pinch and double tap using InteractiveViewer?

here is my code:

@override
Widget build(BuildContext context) {
  return Center(
    child: InteractiveViewer(
      boundaryMargin: EdgeInsets.all(80),
      panEnabled: false,
      scaleEnabled: true,
      minScale: 1.0,
      maxScale: 2.2,
      child: Image.network("https://pngimg.com/uploads/muffin/muffin_PNG123.png",
        fit: BoxFit.fitWidth,
      )
    ),
  );
}

Solution

  • You can use a GestureDetector, that gives you the position of the click and with that you can zoom with the TransformationController at the click position:

    final _transformationController = TransformationController();
    TapDownDetails _doubleTapDetails;
    
    @override
    Widget build(BuildContext context) {
      return GestureDetector(
        onDoubleTapDown: (d) => _doubleTapDetails = d,
        onDoubleTap: _handleDoubleTap,
        child: Center(
          child: InteractiveViewer(
            transformationController: _transformationController,
            /* ... */
          ),
        ),
      );
    }
    
    void _handleDoubleTap() {
      if (_transformationController.value != Matrix4.identity()) {
        _transformationController.value = Matrix4.identity();
      } else {
        final position = _doubleTapDetails.localPosition;
        // For a 3x zoom
        _transformationController.value = Matrix4.identity()
          ..translate(-position.dx * 2, -position.dy * 2)
          ..scale(3.0);
        // Fox a 2x zoom
        // ..translate(-position.dx, -position.dy)
        // ..scale(2.0);
      }
    }