I want to scale a widget using gesture detector that can also be dragged around the screen in flutter

454 Views Asked by At

So far I've been able to drag the widget around the screen but the scale doesn't change. I've printed the scale and it is always shown to be one.

Here's the code I've written

            Positioned(
              top: (_y1 - _radius1).toDouble(),
              left: (_x1 - _radius1).toDouble(),
              child: GestureDetector(
                onScaleStart: (details) {
                  _baseScaleFactor = _scaleFactor;
                },
                onScaleUpdate: (ScaleUpdateDetails details) {
                  setState(() {
                    _scaleFactor = _baseScaleFactor * details.scale;
                    _radius1 = _scaleFactor * _radius1;
                    _x1 = min(392,
                        max(0, _x1 + details.focalPointDelta.dx.toInt()));
                    _y1 = min(512,
                        max(0, _y1 + details.focalPointDelta.dy.toInt()));
                    debugPrint("x1: $_x1\ty1: $_y1");
                    debugPrint("R1:$_radius1 \tScale: ${details.scale}");
                    debugPrint("focal: ${details.focalPoint}");
                    debugPrint("focal delta: ${details.focalPointDelta}");
                    debugPrint(
                        "horizontal Scale: ${details.horizontalScale}");
                    debugPrint("Vertical Scale: ${details.verticalScale}");
                  });
                },

                child: Container(
                  height: _radius1.toDouble() * 2,
                  width: _radius1.toDouble() * 2,
                  decoration: BoxDecoration(
                    color: const Color.fromARGB(148, 180, 60, 52),
                    borderRadius:
                        BorderRadius.circular(_radius1.toDouble()),
                  ),
                  child: CustomPaint(
                    painter: CirclePainter(_radius1.toInt(),
                        _radius1.toInt(), _radius1.toInt()),
                  ),
                ),
                // child: CustomPaint(
                //   painter: CirclePainter(0, 0, _radius1),
                // ),
              ),
            ),
1

There are 1 best solutions below

0
user3144028 On

on scale update is called with one or two fingers touching the screen. you should check how many pointers in details. something like this:

class ZoomAndDragExample extends StatefulWidget {


const ZoomAndDragExample({super.key, required this.child});

  final Widget child;

  @override
  _ZoomAndDragExampleState createState() => _ZoomAndDragExampleState();
}

    class _ZoomAndDragExampleState extends State<ZoomAndDragExample> {
  double _scale = 1.0;
  double _previousScale = 1.0;
  Offset _offset = Offset.zero;
  Offset _previousOffset = Offset.zero;
  Offset _currentFocalPoint = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onScaleStart: (details) {
        if (details.pointerCount == 2){
          _previousScale = _scale;
          _currentFocalPoint = details.focalPoint;
        } else if(details.pointerCount == 1){
          _previousOffset = details.focalPoint;
        }
      },
      onScaleUpdate: (details) {
        setState(() {
          if (details.pointerCount == 2) {
            _scale = _previousScale * details.scale;
            _scale = _scale.clamp(1, 10);
          }

          if (details.pointerCount == 1) {
            final Offset delta = details.focalPoint - _previousOffset;
            _previousOffset = details.focalPoint;
            _offset += delta;
        }
        });
      },
      onScaleEnd: (details) {
        _previousScale = 1.0;
      },
      child: Transform(
          alignment: Alignment.center,
          transform: Matrix4.identity()
            ..translate(_offset.dx, _offset.dy)
            ..scale(_scale),
          child: Container(color:colors.red,width:100,height:100,
        ),
    );
  }
}