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

TouchEvents on Viewgroups: Catch MOVE_OVER on views

我正在尝试弄清楚如何在各种 类.

中安排我的 onInterceptTouchEventonTouchEvent 覆盖
 ButtonContainer            
          |                    
          |-----------+        
       Button      BitContainer
                            |  
                ------------|  
              View1       View2

ButtonContainer 和BitContainer 是RelativeLayouts,Button、View1 和View2 都是带有可绘制圆形背景的imageview。 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 手势。

事件是否可能在其他地方被捕获?我注意到如果 View 1 可见并且 below 甚至 ACTION_DOWN 上的 TouchEvent 位置,它会检测到后续的 ACTION_MOVE 事件......但是如果 TouchEvent 发生视图 2 或按钮,然后视图 1 不响应 ACTION_MOVE

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

我假设消耗意味着 'is directly beneath' 而不是 'is part of the ViewGroup'。那是对的吗?有没有办法将事件传递给View1,以便通知它 ACTION_MOVE?

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

Button1 returns true 从 OnTouchEvent if action = ACTION_DOWN. 时是 ACTION_MOVE, then return false.

ButtonContainer returns true on onInterceptTouchEvent when action is ACTION_MOVE and then calls the dispatchTouchEvent of BitContainer, it calls dispatchTouchEvent on all t's child使用 for 循环的视图

从那里,您现在可以在每个子视图中编写一个方法来检查 touchevent 的 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)
}