解决方案
增加transform参数
startTrackingPointer(event.pointer,event.transform);
历程记录
一、需求出现
在一个可滑动的页面上自定义一个可上下左右滑动的控件。
二、需求实现
1.最初实现
1.用CustomPaint画出控件。
2.外面包裹一个GestureDetector再分别传入onPanDown、onPanUpdate、onPanEnd方法,根据回调改变属性值。
2.问题出现
发现手势效果有问题,操作自定义控件时,自定义控件无响应,反而是可滑动的父控件在响应。
推测手势有优先级问题,因为我不用onPan*方法,改用onVertical*+onHorizontal*+onTapDown就能实现需求,但用这个传参比较多,我不喜欢,所以还是想找到解决方案。
3.Google找方案
找到一篇文章对我帮助很大,我知道了需要用到RawGestureDetector自己去处理手势情况,刚好他里面也有完整的代码,我就直接拿来用了。
主要覆写两个方法:
1.addAllowedPointer()
2.handleEvent()
代码如下:
@override
void addAllowedPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer);
if (onPanDown(event)) {
resolve(GestureDisposition.accepted);
} else {
stopTrackingPointer(event.pointer);
}
}
@override
void handleEvent(PointerEvent event) {
if (event is PointerMoveEvent) {
onPanUpdate(event);
} else if (event is PointerUpEvent || event is PointerCancelEvent) {
onPanEnd(event);
stopTrackingPointer(event.pointer);
}
}
复制代码
博主覆写的是addPointer与handleEvent,我将addPointer改为了addAllowedPointer,实际上用addAllowedPointer才是最好的方案。
其中还有一点对我理解手势很有帮助:在main方法中增加debugPrintGestureArenaDiagnostics = true ;
,当有手势动作时,在控制台会打印当前所有参与竞争的手势和最后胜出的手势。
使用了博主的代码后,我发现当手势操作出现在我自定义控件上时全部都被我的控件捕捉到了,但同时有一一个新的问题出现了。
4.localPosition值不对
使用localPosition时,发现在onPanDown中值是对的,但是在onPanUpdate和onPanEnd中它的值和position一样,当时各种怀疑都有,Google了很久,也乱试了一下,都没找到方案。所以去源码里看了一下发现
当localPosition为空时会将position的值赋给localPosition。
5.源码中找方案
我自定义的GestureRecognizer继承自OneSequenceGestureRecognizer,所以我想可以看看系统实现的OneSequenceGestureRecognizer是怎么处理手势的。
发现很多,那就看HorizontalDragGestureRecognizer吧。
- 第一步,看addAllowedPointer方法。没看出什么有用信息
- 第二步,再看handleEvent方法,也没看出什么信息
- 第三步
- 怀疑Google的有bug(因为我之前发现一个bug,去GitHub上提了issue,到现在也没解决)
- 反思自己看的不仔细,刚才看的都比较简略
- 第四步,再看一遍,从addAllowedPointer方法开始
这次发现了,红框部分我少了一个transform参数,添加后测试,问题解决。
【END】