首页 > 解决方案 > Flutter:如何控制相互冲突的手势?

问题描述

目前,我在带有 Customscrollview 的列中使用 photoview(类似于颤振的交互式查看器)小部件。所以基本上我有一个应用程序链接 instagram 提要。然而,捏缩放功能有点问题,因为海关滚动视图有时会采用捏手势进行滚动。

所以我需要的是,只要有“多点触控”,我就需要 PhotoViewGestureRecognizer 来赢得对抗 VerticalDragGestureRecognizer 的竞技场。

这是我的手势调试日志:

I/flutter (12956): Gesture arena 12   ❙ Adding: PhotoViewGestureRecognizer#6bdab(debugOwner: PhotoViewGestureDetector)
I/flutter (12956): Gesture arena 12   ❙ Adding: DoubleTapGestureRecognizer#6e985(debugOwner: PhotoViewGestureDetector)
I/flutter (12956): Gesture arena 12   ❙ Adding: VerticalDragGestureRecognizer#b7e88(start behavior: down)
I/flutter (12956): Gesture arena 12   ❙ Adding: HorizontalDragGestureRecognizer#d6b73(start behavior: down)
I/flutter (12956): Gesture arena 12   ❙ Closing with 4 members.
I/flutter (12956): Gesture arena 12   ❙ Rejecting: DoubleTapGestureRecognizer#6e985(debugOwner: PhotoViewGestureDetector)
I/flutter (12956): Gesture arena 11   ❙ Accepting: VerticalDragGestureRecognizer#b7e88(start behavior: down)
I/flutter (12956): Gesture arena 11   ❙ Self-declared winner: VerticalDragGestureRecognizer#b7e88(start behavior: down)
I/flutter (12956): Gesture arena 12   ❙ Accepting: VerticalDragGestureRecognizer#b7e88(start behavior: down)
I/flutter (12956): Gesture arena 12   ❙ Self-declared winner: VerticalDragGestureRecognizer#b7e88(start behavior: down)


标签: androidflutterdartgesture

解决方案


我通过使用这个类解决了这个问题

import 'package:flutter/gestures.dart';

class TouchCountRecognizer extends OneSequenceGestureRecognizer {
  TouchCountRecognizer(this.onMultiTouchUpdated);
  Function(bool) onMultiTouchUpdated;
  int touchcount = 0;

  @override
  void addPointer(PointerDownEvent event) {
    startTrackingPointer(event.pointer);
    if (touchcount < 1) {
      //resolve(GestureDisposition.rejected);
      //_p = event.pointer;

      onMultiTouchUpdated(false);
    } else {
      onMultiTouchUpdated(true);
      //resolve(GestureDisposition.accepted);
    }
    touchcount++;
  }

  @override
  String get debugDescription => 'touch count recognizer';

  @override
  void didStopTrackingLastPointer(int pointer) {}

  @override
  void handleEvent(PointerEvent event) {
    if (!event.down) {
      touchcount--;
      if (touchcount < 1) {
        onMultiTouchUpdated(false);
      }
    }
  }
}

然后像这样包装您的自定义滚动视图:

RawGestureDetector(
            gestures: <Type, GestureRecognizerFactory>{
              TouchCountRecognizer:
                  GestureRecognizerFactoryWithHandlers<TouchCountRecognizer>(
                () => TouchCountRecognizer(this.onMultiTouchUpdated),
                (TouchCountRecognizer instance) {},
              ),
            },
            child: NotificationListener(
              // ignore: missing_return
              onNotification: (notification) {
                if (notification is ScrollStartNotification) {
                  _scrolling = true;
                }
                if (notification is ScrollUpdateNotification) {}
                if (notification is ScrollEndNotification) {
                  _scrolling = false;
                }
              },
              child: CustomScrollView(physics: _scrollPhysics,......)

然后让多点触控回调是这样的:

 onMultiTouchUpdated(bool status) {
    _multiTouch = status;
    //setState(() {});
  }

有条件地定义滚动物理:

 if (!_scrolling && _multiTouch) {
      _scrollPhysics = NeverScrollableScrollPhysics();
    } else {
      _scrollPhysics = AlwaysScrollableScrollPhysics();
    }

基本上,我们要做的是检测用户是尝试进行多点触控还是单点触控,并相应地优先选择捏合或滚动动作。


推荐阅读