val gestureDetector = GestureDetector(this.fragment.activity, ScrollGestureListener(scrollView))
scrollView.setOnTouchListener(OnTouchListener { view, event ->
gestureDetector.onTouchEvent(event)
return@OnTouchListener false
})
internal inner class ScrollGestureListener(view: View) : GestureDetector.SimpleOnGestureListener() {
override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
this@DocumentViewer.onDrag()
return true
}
}
当使用compileSdkVersion 30时,我的应用程序会在onScroll
函数上崩溃,因为它总是接收到第一个参数的空值。我通过使第一个参数变成可选项来解决这个问题:
override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
现在我正在尝试将compileSdkVersion更新到33,那么上面的代码行将不能编译。但是,如果我恢复标准函数签名,那么当我滚动滚动视图时,应用程序会再次崩溃。
这个SO帖子上的评论说:"如果除手势检测器以外的其他东西消耗了ACTION_DOWN事件,你就会遇到这样的崩溃。" 但是我无法弄清楚还有什么东西会这样做。在这个片段的一些其他视图上我有手势检测器,但是如果我注释掉所有这些代码,崩溃仍然存在。
我暂时添加了onDown
的实现到我的ScrollGestureListener
,但它从未被调用过,所以似乎与ACTION_DOWN有关。
查看GestureDetector.java
的源代码,我发现它发送给onScroll
的第一个参数是mCurrentDownEvent
,所以这也似乎与ACTION_DOWN有关。但是,如果我在Android Studio中为GestureDetector.java
添加断点,mCurrentDownEvent
从未显示为空。而且,它始终与作为第二个参数传递的事件(ev
)相同--GestureDetector
只是将mCurrentDownEvent
设置为ev
的副本。
看起来当GestureDetector
调用onScroll
时,崩溃发生了,因为我onScroll
方法中的断点没有被触发,如果我删除我的onScroll
重写,同样的崩溃也会发生 -- 显然只调用超类实现的onScroll
就会导致崩溃。以下是控制台中显示的内容:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.arlomedia.bandhelper, PID: 18797
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter e1
at com.arlomedia.bandhelper.helpers.DocumentViewer$ScrollGestureListener.onScroll(Unknown Source:2)
at android.view.GestureDetector.onTouchEvent(GestureDetector.java:788)
at com.arlomedia.bandhelper.helpers.DocumentViewer.viewDocument$lambda-9(DocumentViewer.kt:1398)
at com.arlomedia.bandhelper.helpers.DocumentViewer.$r8$lambda$kyj-4h2jNAIkIYOWSE7_HVetJAg(Unknown Source:0)
at com.arlomedia.bandhelper.helpers.DocumentViewer$$ExternalSyntheticLambda7.onTouch(Unknown Source:6)
at android.view.View.dispatchTouchEvent(View.java:15147)
在调用onTouchEvent
之前,我尝试在我的OnTouchListener
中添加一些检查--类似于这样:
if (event != null) {
gestureDetector.onTouchEvent(event)
}
但是在这里 event
永远不会为空,在查看其属性时,我没有看到任何可以检查是否会导致崩溃的东西。
另一个潜在的线索是,只有当我的手指在调用 onTouchEvent
时仍然触摸屏幕时,才会调用 onScroll
。通常情况下是这样的,但我尝试了延迟其调用:
val runnable = Runnable {
gestureDetector.onTouchEvent(event)
}
App.instance.timerHandler.postDelayed(runnable, 1000)
如果我进行滚动并在一秒钟内从屏幕上抬起手指,则不会调用onScroll
,也不会崩溃。 如果我进行滚动并将手指放在屏幕上超过一秒钟,则会调用onScroll
并发生崩溃。
我可以想象有两种方法来修复这个问题:在调用onTouchEvent
之前,在我的OnTouchListener
中验证事件,或者找出是什么导致GestureDetector
向onScroll
发送无效的事件。 但我对两者都没有更多的想法。 是否有其他人有想法?