视图组上的 TouchEvents:在视图上捕获 MOVE_OVER

问题描述

我想弄清楚如何在各种类中安排我的 onInterceptTouchEventonTouchEvent 覆盖。

 ButtonContainer            
          |                    
          |-----------+        
       Button      BitContainer
                            |  
                ------------|  
              View1       View2

ButtonContainer 和 BitContainer 是 RelativeLayouts,Button、View1 和 View2 都是具有可绘制圆形背景的图像视图。 View1 和 View2 最初不可见。

目标是让 ButtonContainer 通过使 view1 和 view2 可见来响应初始 ACTION_DOWN 事件。在 ACTION_MOVE 事件上,如果触摸从 Button 移动到 View1,则应调用 View1 onTouchEvent 方法

我想我可以在 ButtonContainer 上使用 onInterceptTouchEvent 并在 ACTION_DOWN 的情况下将其设置为 true,但在所有其他情况下将其设置为 false。这不应该阻止 ACTION_MOVE 事件直接进入 ButtonContainer onTouch 并让它遍历树吗?如果是这样,那么 ACTION_MOVE 事件将遵循通常的事件流并被其他视图检测到,即视图 1 和 2。

无论我做什么,都无法让 view1 或 2 中的 onTouchEvent 方法响应 ACTION_MOVE 手势。

该事件是否可能在其他地方被发现?我注意到,如果视图 1 可见并且低于 ACTION_DOWN 上的 TouchEvent 位置,它会检测到后续的 ACTION_MOVE 事件……但是如果 TouchEvent 发生在视图 2 上或按钮,则视图 1 不会响应 ACTION_MOVE

编辑:好的,所以我读了更多,似乎如果一个对象'不消耗 ACTION_DOWN 事件,那么它不会消耗任何进一步的事件(出于效率原因)'...

我认为消费意味着“直接在下方”而不是“是 ViewGroup 的一部分”。那是对的吗?有没有办法将事件传递给 View1,以便它可以收到 ACTION_MOVE 的通知

解决方法

对于其他面临此问题的人,诀窍是手动进行事件调度。

Button1 从 OnTouchEvent 返回 true 如果 action = ACTION_DOWN. 当它是 ACTION_MOVE 时,则返回 false。

当 action 为 onInterceptTouchEvent 时,ButtonContainer 在 ACTION_MOVE 上返回 true,然后调用 BitContainer 的 dispatchTouchEvent,它使用 for 循环在所有 t 的子视图上调用 dispatchTouchEvent>

从那里开始,您现在可以在每个子视图中编写一个方法来检查触摸事件的 x 位置是否在它们自己的 getLocationOnScreen() 坐标内。

这里以ButtonContainer上的onInterceptTouch事件,BitContainer上的dispatchTouchEvent为例:

按钮容器

override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
    if (ev != null) {
        if (ev.action == MotionEvent.ACTION_MOVE) {
            bitContainer.dispatchTouchEvent(ev)
            return true
        }
    }
    return super.onInterceptTouchEvent(ev)
}

比特容器

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    if (ev != null) {
        if (ev.action == MotionEvent.ACTION_MOVE) {
            for (i in 0 until this.getChildCount()) {
                this.getChildAt(i).dispatchTouchEvent(ev)
            }

        }
    }
    return super.dispatchTouchEvent(ev)
}