我使用手势检测器从滚动视图捕获滚动事件:
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,而上面的行将不再编译。但是如果我恢复到标准函数签名,那么当我滚动滚动视图时,应用程序会再次崩溃。
this SO post上的一条评论说:“如果手势检测器以外的东西消耗了ACTION_DOWN事件,您就会遇到这样的崩溃。”但我想不出还能做什么。我在这个片段中的其他视图上有手势检测器,但是如果我注释掉所有的代码,崩溃仍然存在。
我暂时将onDown的一个实现添加到我的ScrollGestureListener中,它从未被调用过,所以这似乎与ACTION_DOWN注释有关。
查看GestureDetector.java的源代码,我发现它发送给onScroll的第一个参数是mCurrentDownEvent,因此这似乎也与ACTION_DOWN注释有关。但是如果我在Android中向GestureDetector.java添加断点,mCurrentDownEvent就不会显示为null。而且,它总是与作为第二个参数(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)在调用OnTouchListener之前,我尝试在onTouchEvent中添加某种检查--如下所示:
if (event != null) {
gestureDetector.onTouchEvent(event)
}但是event在这里从来都不是空的,当查看它的属性时,我看不到任何我可以检查的东西来确定它是否会导致崩溃。
另一个潜在的线索是,只有当我的手指在调用onScroll时仍在屏幕上时,才会调用onTouchEvent。通常情况是这样的,但我试着像这样推迟它的通话:
val runnable = Runnable {
gestureDetector.onTouchEvent(event)
}
App.instance.timerHandler.postDelayed(runnable, 1000)然后,如果我在一秒钟内执行滚动并将手指从屏幕上抬起,onScroll就不会被调用,也不会发生崩溃。如果我执行滚动并将手指放在屏幕上超过1秒,则调用onScroll,就会发生崩溃。
我可以想象两种解决这个问题的方法:在调用OnTouchListener之前在onTouchEvent中验证事件,或者找出是什么导致GestureDetector向onScroll发送无效事件。但我对这两方面的想法都没有了。还有其他人有主意吗?
发布于 2022-10-10 22:50:37
我在一个新的片段中一步一步地重建了这个功能,以隔离问题。滚动视图被包装在TextView周围,以便使文本视图可平移(惯性滚动),但我在该文本视图上也有一个OnTouchListener,因此我可以检测到夹点手势,以调整文本的大小。显然,这是吸收了onDown事件,所以周围的滚动视图没有收到它。
我假设有一种方法可以在两个视图之间共享onDown事件,但在我的示例中,将夹点手势检测器从内部文本视图移动到外部滚动视图更容易,因此滚动手势检测器和夹点手势检测器位于相同的视图上--类似这样:
val scrollGestureDetector = GestureDetector(this.fragment.activity, ScrollGestureListener(scrollView))
val pinchGestureDetector = GestureDetector(this.fragment.activity, PinchGestureListener(scrollView))
scrollView.setOnTouchListener(OnTouchListener { view, event ->
scrollGestureDetector.onTouchEvent(event)
pinchGestureDetector.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
}
}
internal inner class PinchGestureListener(view: View) : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
this@DocumentViewer.onZoom()
return true
}
}https://stackoverflow.com/questions/73991818
复制相似问题