前言:需要做一个长按弹窗的功能,但是
InkWell没有点击位置的坐标回调,而GestureDetector没有长按的动画效果,想全都要那最方便的就是把他们嵌套起来,但是无论谁作为子widget都会默认拦截上层的手势事件。
自定义GestureRecognizer
Flutter框架中已经定义了很多种类型的GestureRecognizer,想要使用长按效果,我们直接继承LongPressGestureRecognizer,别的动作如双击、拖动也有对应的GestureRecognizer
class CustomLongPressGestureRecognizer extends LongPressGestureRecognizer {
@override
void rejectGesture(int pointer) {
// super.rejectGesture(pointer);
// 直接接受手势,则子widget和自身都会处理手势事件
super.acceptGesture(pointer);
}
}
在rejectGesture中接受所有的点,就不会冲突了
定义一个MultiLongPressStartGesture组件
把上面定义的CustomLongPressGestureRecognizer放在一个组件里,从外面传入要包含的子widget和长按callback,减少使用的代码量
class MultiLongPressStartGesture extends StatelessWidget {
const MultiLongPressStartGesture({
Key? key,
required this.child,
this.callback,
}) : super(key: key);
final Widget child;
// 只处理长按事件,可根据需要设置其他类型callback
final GestureLongPressStartCallback? callback;
@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: {
CustomLongPressGestureRecognizer: GestureRecognizerFactoryWithHandlers<
CustomLongPressGestureRecognizer>(
() => CustomLongPressGestureRecognizer(),
(recognizer) {
// 把对应类型的callback给自定义的recognizer
recognizer.onLongPressStart = callback;
},
),
},
child: child,
);
}
}
GestureLongPressStartCallback回调包含一个LongPressStartDetails,里面有长按位置的坐标
使用
MultiLongPressStartGesture(
child: InkWell(
onTap: () {
// tap event
},
child: childWidget(),
),
callback: (details) {
// 长按的动作
},
),
在MultiLongPressStartGesture中嵌入InkWell,在callback中就可以有点击坐标的回调了,InkWell的动画和点击事件也没有影响,可以正常使用