Search code examples
fluttergesturedetector

Zoom and pan widget within another widget


I want to have a widget A that is placed in the center of and on top of a widget B. While widget B is fixed in position, widget A can be panned and zoomed, but can never leave the boundaries defined by widget B - as if widget B was a frame for widget A.

In other words: Picture it as a small red container placed in the middle of a large green container. The little red container can be moved around within the green container and can be made larger or smaller, but never exceed the size of the green container.

I've been researching this for a while and haven't found a working solution. I'm assuming I have just phrased my search wrong and would love for someone to point me in the right direction. All my attempts with InteractiveViewer have not been successful.


Solution

  • enter image description here

    Instead of using InteractiveViewer, I use GestureDetector

    class ZoomInOutWidget extends StatefulWidget {
      @override
      _ZoomInOutWidgetState createState() => _ZoomInOutWidgetState();
    }
    
    class _ZoomInOutWidgetState extends State<ZoomInOutWidget> {
      double _scale = 1.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Zoomable Widget'),
          ),
          body: Center(
            child: GestureDetector(
              onScaleUpdate: (ScaleUpdateDetails details) {
                setState(() {
                  // Apply scaling factor
                  _scale = details.scale.clamp(1.0, 3.0);
                });
              },
              child: Container(
                color: Colors.green,
                width: 300,
                height: 300,
                child: Center(
                  child: Transform.scale(
                    scale: _scale,
                    child: Container(
                      color: Colors.red,
                      width: 100,
                      height: 100,
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }