Flutter `GestureRecognizer` 仅响应两指手势

问题描述 投票:0回答:1

如何在 Flutter 中创建一个仅响应两指手势的

GestureRecognizer
,并将单指手势传递到 arena 中的其他小部件?

在我的 Flutter 应用程序中,我在

GoogleMap
内有一个
SingleChildScrollView
小部件。
GoogleMap
小部件采用
gestureRecognizers
参数,我已将其设置为以下内容,否则甚至无法与地图交互(ScrollView 获取所有触摸事件,至少 95% 的时间...)

  gestureRecognizers: const {
    Factory<OneSequenceGestureRecognizer>(
      EagerGestureRecognizer.new,
    ),
  },

有了这个

GestureRecognizer
,Google 地图小部件即可响应单指手势(平移)和两指手势(缩放/平移)。我希望该小部件仅响应两指手势,因为当前用一根手指在地图小部件上拖动会中断用户向上或向下滚动视图的能力。所以我想要单指手势去 ScrollView,两指手势去 Google 地图。 (出于同样的原因,Google 地图网络小部件需要两指手势进行平移......)

如何用手势识别器替换

EagerGestureRecognizer
,使地图仅在两根手指按下时平移,否则将单指手势传递到滚动视图?

flutter dart user-interface gesture
1个回答
0
投票

好吧,我明白了。诀窍是您需要使用

GestureAreaManager
来按住第一个触摸点,直到第二个触摸点按下:

class TwoFingerPanZoomEagerGestureRecognizer extends EagerGestureRecognizer {
  final _gestureArenaManager = GestureArenaManager();
  int? _firstPointer;
  int? _secondPointer;

  @override
  void addAllowedPointer(PointerDownEvent event) {
    startTrackingPointer(event.pointer);
    if (_firstPointer == null) {
      // If 1 touchpoint is down, hold the pointer until the 2nd touchpoint
      // is down
      _firstPointer = event.pointer;
      _gestureArenaManager.hold(event.pointer);
    } else if (_secondPointer == null) {
      // If 2 touchpoints are down, release the first pointer, and accept
      // both touchpoints
      _gestureArenaManager.release(_firstPointer!);
      resolvePointer(_firstPointer!, GestureDisposition.accepted);
      _secondPointer = event.pointer;
      resolvePointer(_secondPointer!, GestureDisposition.accepted);
    } else {
      // If 3rd touchpoint is down, ignore it
      resolvePointer(event.pointer, GestureDisposition.rejected);
    }
  }

  @override
  void handleEvent(PointerEvent event) {
    if (event is PointerUpEvent) {
      stopTrackingPointer(event.pointer);
      if (_secondPointer == event.pointer) {
        // Second pointer was lifted
        stopTrackingPointer(_secondPointer!);
        _secondPointer = null;
      } else if (_firstPointer == event.pointer) {
        // First pointer was lifted
        stopTrackingPointer(_firstPointer!);
        _gestureArenaManager.release(_firstPointer!);
        // Move second pointer to first pointer slot
        _firstPointer = _secondPointer;
        _secondPointer = null;
      }
    } else {
      super.handleEvent(event);
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.