如何在 Flutter 中创建一个仅响应两指手势的
GestureRecognizer
,并将单指手势传递到 arena 中的其他小部件?
在我的 Flutter 应用程序中,我在
GoogleMap
内有一个 SingleChildScrollView
小部件。 GoogleMap
小部件采用 gestureRecognizers
参数,我已将其设置为以下内容,否则甚至无法与地图交互(ScrollView 获取所有触摸事件,至少 95% 的时间...)
gestureRecognizers: const {
Factory<OneSequenceGestureRecognizer>(
EagerGestureRecognizer.new,
),
},
有了这个
GestureRecognizer
,Google 地图小部件即可响应单指手势(平移)和两指手势(缩放/平移)。我希望该小部件仅响应两指手势,因为当前用一根手指在地图小部件上拖动会中断用户向上或向下滚动视图的能力。所以我想要单指手势去 ScrollView,两指手势去 Google 地图。 (出于同样的原因,Google 地图网络小部件需要两指手势进行平移......)
如何用手势识别器替换
EagerGestureRecognizer
,使地图仅在两根手指按下时平移,否则将单指手势传递到滚动视图?
好吧,我明白了。诀窍是您需要使用
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);
}
}
}