首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SimpleOnGestureListener.onScroll接收空值并崩溃

SimpleOnGestureListener.onScroll接收空值并崩溃
EN

Stack Overflow用户
提问于 2022-10-07 19:22:27
回答 1查看 180关注 0票数 3

我使用手势检测器从滚动视图捕获滚动事件:

代码语言:javascript
复制
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函数,因为第一个参数总是收到一个空值。为此,我将第一个参数设为可选参数:

代码语言:javascript
复制
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的超类实现就会导致崩溃。下面是控制台中显示的内容:

代码语言:javascript
复制
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中添加某种检查--如下所示:

代码语言:javascript
复制
if (event != null) {
    gestureDetector.onTouchEvent(event)
}

但是event在这里从来都不是空的,当查看它的属性时,我看不到任何我可以检查的东西来确定它是否会导致崩溃。

另一个潜在的线索是,只有当我的手指在调用onScroll时仍在屏幕上时,才会调用onTouchEvent。通常情况是这样的,但我试着像这样推迟它的通话:

代码语言:javascript
复制
val runnable = Runnable {
    gestureDetector.onTouchEvent(event)
}
App.instance.timerHandler.postDelayed(runnable, 1000)

然后,如果我在一秒钟内执行滚动并将手指从屏幕上抬起,onScroll就不会被调用,也不会发生崩溃。如果我执行滚动并将手指放在屏幕上超过1秒,则调用onScroll,就会发生崩溃。

我可以想象两种解决这个问题的方法:在调用OnTouchListener之前在onTouchEvent中验证事件,或者找出是什么导致GestureDetectoronScroll发送无效事件。但我对这两方面的想法都没有了。还有其他人有主意吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-10 22:50:37

我在一个新的片段中一步一步地重建了这个功能,以隔离问题。滚动视图被包装在TextView周围,以便使文本视图可平移(惯性滚动),但我在该文本视图上也有一个OnTouchListener,因此我可以检测到夹点手势,以调整文本的大小。显然,这是吸收了onDown事件,所以周围的滚动视图没有收到它。

我假设有一种方法可以在两个视图之间共享onDown事件,但在我的示例中,将夹点手势检测器从内部文本视图移动到外部滚动视图更容易,因此滚动手势检测器和夹点手势检测器位于相同的视图上--类似这样:

代码语言:javascript
复制
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
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73991818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档