Flutter: 如何同时使用拖动和缩放手势?

7
我正在使用Flutter创建一个绘图画布,想要同时使用缩放(用于缩放、平移和旋转)和手势绘制。但由于缩放是Pan的超集,Flutter不允许这样做。是否有任何解决方法?
我尝试创建自己的自定义手势识别器,以检测屏幕上的指针数量。如果两个指针在短时间内(比如1秒)接触屏幕,则缩放接管;否则,平移将使用第一个触摸屏幕的指针。我正在使用matrix_gesture_detector包来实现缩放部分。
以下是我的自定义手势识别器的代码:
class ScaleAndPanRecognizer extends OneSequenceGestureRecognizer {
  var manager = GestureArenaManager();
  final Function onPanDown;
  final Function onPanUpdate;
  final Function onPanEnd;
  ScaleAndPanRecognizer({
    @required this.onPanDown,
    @required this.onPanUpdate,
    @required this.onPanEnd,
  });

  int numPointers = 0;
  int timeFrame = 1;
  int pointer1;
  int pointer2;
  var time1;
  var time2;
  var position1;

  @override
  void addPointer(PointerDownEvent event) {
    print(numPointers);
    if (numPointers == 0) {
      pointer1 = event.pointer;
      print(pointer1);
      position1 = event.localPosition;
      manager.hold(pointer1); //hold the assignment for this pointer for now
      startTrackingPointer(pointer1);

      numPointers += 1;
      time1 = DateTime.now();
    } else if (numPointers == 1) {
      pointer2 = event.pointer;
      print(pointer2);
      resolvePointer(pointer2, GestureDisposition.rejected);
      time2 = DateTime.now();
      var diff = time2.difference(time1);
      print(diff);
      if (diff <= Duration(seconds: timeFrame)) {
        manager.release(pointer1);
        resolvePointer(pointer1, GestureDisposition.rejected);
      } else {
        resolvePointer(pointer1, GestureDisposition.accepted);
        manager.release(pointer1);
        onPanDown(position1);
      }
      numPointers = 0;
    }
  }

  @override
  void handleEvent(PointerEvent event) {
    if (event is PointerMoveEvent) {
      onPanUpdate(event.localPosition);
    }
    if (event is PointerUpEvent) {
      onPanEnd();
      stopTrackingPointer(event.pointer);
    }
  }

  @override
  String get debugDescription => 'only one pointer recognizer';

  @override
  void didStopTrackingLastPointer(int pointer) {}

}

我正在进行类似的旅程。目前我的解决方案是使用InteractiveViewer:https://github.com/flutter/flutter/blob/b429ec1e8fd737abd58501591e4b6c6f708bfb81/packages/flutter/lib/src/widgets/interactive_viewer.dart 还有一些演示:https://github.com/justinmc/flutter-interactive-viewer-demos/commits?author=justinmc&since=2020-04-01&until=2020-04-28 - Thmsbrhn
3个回答

3
你需要做的是将onPanUpdate, onPanEnd...替换为onScaleUpdate, onScaleEnd...。然后使用details.focalPoint代替details.globalPosition。这样你将得到与Pan相同的行为,同时你现在可以访问details.scaledetails.rotation。以下是一个示例。

之前:

onPanUpdate: (DragUpdateDetails details){
              newPosition = details.globalPosition;
              //scale and rotation missing in pan
            },

之后:

onScaleUpdate: (ScaleUpdateDetails details){
              newPosition = details.focalPoint;
              newRotation = details.rotation;
              newScale = details.scale;
              //scale and rotation now available
            },

希望这能帮到你。我也花了一些时间才弄明白。

1
使用Listener小部件来监听指针事件,然后根据需要处理指针事件以检测比例和平移手势。
  • 1个指针(短时间内按下并松开)=> 点击
  • 1个指针(长时间内按下并松开)=> 双击
  • 1个指针(按下并移动)=> 平移
  • 2个指针 => 缩放和旋转
您可以使用gesture_x_detector来完全支持手势(点击、双击、缩放、旋转、长按等)。

0

当你想使用比例时,不需要平底锅
比例上有一个属性 => pointerCount

if(details.pointerCount == 2){
//we have two finger so we can scale the widget
}else if(details.pointerCount == 1){
//we have one finger so we can do the move or something like we uses in pan 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接