嵌套手势检测器 OnTap 函数

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

我嵌套了

GestureDetetor
,但问题是只有子
GestureDetector
onTap
被执行。我不想覆盖孩子的 onTap,而是希望父母和孩子的 onTap 都执行。这是我的代码:

    GestureDetector(
        onTap: () {
            todo1(); 
        },
        child: GestureDetector(
            onTap: () {
                todo2();
            },
            child: Text("Nested Gesture")))

如何更改此设置以同时调用

todo1()
todo2()
onTap?

编辑:子级是一个可重用的自定义小部件,它有自己的实现,但现在由父级使用,除了其子级之外,父级也有自己的实现

flutter gesturedetector
4个回答
4
投票

我制作了一个快速的自定义手势识别器 - 仅当用户距离初始点击点太远时它才会取消手势。

使用示例:

UniversalTapHandler(
  onTap: () {
    print("Tap 1");
  },
  child: UniversalTapHandler(
    onTap: () {
      print("Tap 2");
    },
    child: Text("Nested Gesture"),
  )
)

源代码:

class UniversalTapHandler extends RawGestureDetector {
  UniversalTapHandler({
    @required GestureTapCallback onTap,
    @required Widget child,
  }):
    super(
      gestures: <Type, GestureRecognizerFactory>{
        _UniversalPointerHandler: GestureRecognizerFactoryWithHandlers<_UniversalPointerHandler>(
          () => _UniversalPointerHandler(onTap: onTap),
          (_) {},
        ),
      },
      child: child,
    );
}

class _UniversalPointerHandler extends OneSequenceGestureRecognizer {
  _UniversalPointerHandler({
    @required this.onTap,
  }): super();

  final GestureTapCallback onTap;

  final _maxDistance = 18; // as in official recognizer by default
  Offset _startPosition;

  void _reset() {
    _startPosition = null;
  }

  @override
  void addPointer(PointerDownEvent event) {
    _startPosition = event.position;
    startTrackingPointer(event.pointer);
    resolve(GestureDisposition.accepted);
  }

  @override
  void handleEvent(PointerEvent event) {
    if (event is PointerUpEvent) {
      stopTrackingPointer(event.pointer);
      if (_startPosition != null) {
        onTap();
      }
    }
    if (event is PointerMoveEvent && _startPosition != null) {
      if ((event.position - _startPosition).distance > _maxDistance) {
        rejectGesture(event.pointer);
        _reset();
      }
    }
    if (event is PointerCancelEvent || event is PointerExitEvent || event is PointerRemovedEvent) {
      _reset();
    }
  }

  @override
  void resolve(GestureDisposition disposition) {
    if (disposition == GestureDisposition.rejected) {
      _reset();
    }
    super.resolve(disposition);
  }

  @override
  void didStopTrackingLastPointer(int pointer) {}

  @override
  String get debugDescription => "_UniversalPointerHandler: Custom Gesture Recognizer";
}

更新 不要忘记导入这个:

import 'package:flutter/gestures.dart';

0
投票

如果您希望父级和子级的 onTap 方法都执行,可以使用以下代码片段:

GestureDetector(
  onTap: () {
    // parent onTap method
  },
  child: GestureDetector(
    onTap: () {
      // child onTap method
    },
    behavior: HitTestBehavior.translucent,
    child: Container(),
  ),
);

行为属性设置为

HitTestBehavior.translucent
,这允许父窗口小部件和子窗口小部件接收点击。


0
投票

官方文档中提到了该问题🤓 - https://api.flutter.dev/flutter/widgets/GestureDetector-class.html#widgets.GestureDetector.3

如果您有两个相互竞争的手势检测器,即使设置为半透明,嵌套的检测器也会获胜,请在父检测器上实现

onTapDown
以仍然接收点击事件。

 GestureDetector(
        onTap: () {
            todo1(); 
        },
        onTapDown: todo1, // this should do the trick
        child: GestureDetector(
            onTap: () {
                todo2();
            },
            child: Text("Nested Gesture")))

-1
投票

您可以在嵌套的 onTap 回调中调用 todo1() :

  GestureDetector(
        onTap: () {
            todo1(); 
        },
        child: GestureDetector(
            onTap: () {
                todo2();
                todo1();
            },
            child: Text("Nested Gesture")))
© www.soinside.com 2019 - 2024. All rights reserved.