Flutter: How to implement Rotate and Pan/Move gesture for any container?

本秂侑毒 提交于 2020-02-23 07:08:12

问题


I have implemented the Scale gesture for the container. Also, I have added onHorizontalDragUpdate and onVerticalDragUpdate. But when I try to add both, I get an exception saying can't implement both with Scale gesture. Even for Pan gesture, it throws the same exception. Below is my code:

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' hide Colors;
 import 'dart: math' as math;

class HomeScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return HomeState();
  }
}

class HomeState extends State<HomeScreen> {

  double _scale = 1.0;
  double _previousScale;
  var yOffset = 400.0;
  var xOffset = 50.0;
  var rotation = 0.0;
  var lastRotation = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.amber,
      body: Stack(
        children: <Widget>[
          stackContainer(),
        ],
      ),
    );
  }

  Widget stackContainer() {

        return Stack(
          children: <Widget>[
            Positioned.fromRect(
              rect: Rect.fromPoints( Offset(xOffset, yOffset),
                  Offset(xOffset+250.0, yOffset+100.0)),
              child: GestureDetector(
                onScaleStart: (scaleDetails) {
                  _previousScale = _scale;
                  print(' scaleStarts = ${scaleDetails.focalPoint}');
                },
                onScaleUpdate: (scaleUpdates){
                  //ScaleUpdateDetails
                  rotation += lastRotation - scaleUpdates.rotation;
                  lastRotation = scaleUpdates.rotation;
                  print("lastRotation = $lastRotation");
                  print(' scaleUpdates = ${scaleUpdates.scale} rotation = ${scaleUpdates.rotation}');
                  setState(() => _scale = _previousScale * scaleUpdates.scale);
                },
                onScaleEnd: (scaleEndDetails) {
                  _previousScale = null;
                  print(' scaleEnds = ${scaleEndDetails.velocity}');
                },
                child:
                Transform(
                  transform: Matrix4.diagonal3( Vector3(_scale, _scale, _scale))..rotateZ(rotation * math.pi/180.0),
              alignment: FractionalOffset.center,
              child: Container(
                color: Colors.red,
              ),
            )
            ,
          ),
        ),
      ],
    );
  }
}

I wanted to move around the red subview and rotate along with the scale.


回答1:


We can use the focalPoint field of ScaleUpdateDetails object, which we get as an argument in the onScaleUpdate function.

Solution related to the above example: We need to update the onScaleUpdate method.

onScaleUpdate: (scaleUpdates) {

      lastRotation += scaleUpdates.rotation;
      var offset = scaleUpdates.focalPoint;
      xOffset = offset.dx;
      yOffset = offset.dy;

      setState(() => _scale = _previousScale * scaleUpdates.scale);
    }

Change 'rect' field of Positioned Widget in above code.

rect: Rect.fromPoints(Offset(xOffset - 125.0, yOffset - 50.0),
              Offset(xOffset + 250.0, yOffset + 100.0))



回答2:


Default GestureRecognizer does not support the recognition of pan/drag and scaling at the same time. I think this is the bug and it should be fixed. To implement such behavior - you need to build you own recogizer RawGestureDetector based on ImmediateMultiDragGestureRecognizer gestures.

I have already implemented class PanAndScalingGestureRecognizer here: https://gist.github.com/comm1x/8ffffd08417053043e079878b4bd8d03

So you can see full example or just copypaste and use.



来源:https://stackoverflow.com/questions/54536275/flutter-how-to-implement-rotate-and-pan-move-gesture-for-any-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!