![](/img/trans.png)
[英]SimpleOnGestureListener.OnScroll isn't calling properly on fast scrolling
[英]SimpleOnGestureListener.onScroll receives a null value and crashes
我正在使用手勢檢測器從滾動視圖中捕獲滾動事件:
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
function 上崩潰,因為第一個參數總是收到 null 值。 我通過將第一個參數設為可選來解決這個問題:
override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
現在我正在嘗試將我的 compileSdkVersion 更新為 33,並且上面的行將不再編譯。 但是,如果我恢復到標准的 function 簽名,那么當我滾動滾動視圖時應用程序會再次崩潰。
對此SO 帖子的評論說,“如果手勢檢測器以外的其他東西消耗 ACTION_DOWN 事件,你會遇到這樣的崩潰。” 但我無法弄清楚還有什么會這樣做。 我在這個片段的其他一些視圖上有手勢檢測器,但如果我注釋掉所有這些代碼,崩潰仍然存在。
我暫時將onDown
的實現添加到我的ScrollGestureListener
並且它從未被調用過,所以這似乎與 ACTION_DOWN 評論有關。
查看GestureDetector.java
的源代碼,我看到它發送給onScroll
的第一個參數是mCurrentDownEvent
,因此這似乎也與 ACTION_DOWN 評論有關。 但是,如果我在 Android Studio 中向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)
在調用onTouchEvent
之前,我已經嘗試向我的OnTouchListener
添加某種檢查 - 如下所示:
if (event != null) {
gestureDetector.onTouchEvent(event)
}
但是這里的event
從來都不是 null,在查看它的屬性時,我看不到任何可以檢查以確定它是否會導致崩潰的東西。
另一個潛在的線索是,只有在調用onScroll
時我的手指仍在屏幕上時,才會調用onTouchEvent
。 通常是這種情況,但我嘗試像這樣延遲它的調用:
val runnable = Runnable {
gestureDetector.onTouchEvent(event)
}
App.instance.timerHandler.postDelayed(runnable, 1000)
然后,如果我執行滾動並在一秒鍾內將手指從屏幕上移開,則不會調用onScroll
並且不會發生崩潰。 如果我執行滾動並將手指放在屏幕上超過一秒鍾,則會調用onScroll
並發生崩潰。
我可以想象兩種解決此問題的方法:在調用OnTouchListener
之前驗證我的onTouchEvent
中的事件,或者找出導致GestureDetector
向onScroll
發送無效事件的原因。 但是我對兩者都沒有想法。 還有其他人有想法嗎?
我在新片段中一次一步地重建此功能以隔離問題。 滾動視圖環繞在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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.