Search code examples
flutterdartzoomingscale

Flutter MatrixGestureDetector - Minimum and maximum scale


My question essentially duplicates the previously asked question: Flutter: How to set a max/min scale using matrix_gesture_detector

I have a MatrixGestureDetector:

  MatrixGestureDetector(
    onMatrixUpdate: (m, tm, sm, rm) {
      setState(() {
        transform = m;
      });
    },
    child: Transform(
      transform: transform,
      child: Image.asset("assets/maps/map.gif"),
    ),
  ),

The picture can be zoomed in and out indefinitely, but I want to limit the minimum and maximum scale.

The solution suggested in the link above is not correct for me. The scale is really limited, but when it reaches its limits, gestures start to be handled incorrectly. The picture starts moving very quickly when you try to zoom in or out when the limits are reached.

Is there any solution to this problem? Maybe there are other packages to solve my problem? PhotoViev did not satisfy me for the reason described here: Flutter PhotoView - Rotation about the point between the fingers


Solution

  • Flutter announced a new version(1.20) and it came with a new widget called InteractiveViewer.

    You can use the InteractiveViewer to achieve what you want by setting a minScale and maxScale.

    This release introduces a new widget, the InteractiveViewer. The InteractiveViewer is designed for building common kinds of interactivity into your app, like pan, zoom, and drag ’n’ drop

    Read more about the release here: Flutter 1.20 Release notes

    I added a demo:

    NOTE: You can only use this widget if you have upgraded to the latest Flutter version (1.20)

    class ZoomImage extends StatelessWidget {
    
      final transformationController = TransformationController();
      
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: InteractiveViewer(
            transformationController: transformationController,
            onInteractionEnd: (details) {
              setState(() {
                // unzoom when interaction has ended
                transformationController.toScene(Offset.zero);
              });
            },
            // set the boundary margin for the image 
            boundaryMargin: EdgeInsets.all(20.0),
            // set min scale here
            minScale: 0.1,
            // set maximum scall here
            maxScale: 1.6,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(18.0),
              child: Image.asset('assets/maps/map.gif'),
            ),
          ),
        );
      }
    }