我嵌套了
GestureDetetor
,但问题是只有子GestureDetector
的onTap
被执行。我不想覆盖孩子的 onTap,而是希望父母和孩子的 onTap 都执行。这是我的代码:
GestureDetector(
onTap: () {
todo1();
},
child: GestureDetector(
onTap: () {
todo2();
},
child: Text("Nested Gesture")))
如何更改此设置以同时调用
todo1()
和 todo2()
onTap?
编辑:子级是一个可重用的自定义小部件,它有自己的实现,但现在由父级使用,除了其子级之外,父级也有自己的实现
我制作了一个快速的自定义手势识别器 - 仅当用户距离初始点击点太远时它才会取消手势。
使用示例:
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';
如果您希望父级和子级的 onTap 方法都执行,可以使用以下代码片段:
GestureDetector(
onTap: () {
// parent onTap method
},
child: GestureDetector(
onTap: () {
// child onTap method
},
behavior: HitTestBehavior.translucent,
child: Container(),
),
);
行为属性设置为
HitTestBehavior.translucent
,这允许父窗口小部件和子窗口小部件接收点击。
官方文档中提到了该问题🤓 - 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")))
您可以在嵌套的 onTap 回调中调用 todo1() :
GestureDetector(
onTap: () {
todo1();
},
child: GestureDetector(
onTap: () {
todo2();
todo1();
},
child: Text("Nested Gesture")))