欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 事件传递

程序员文章站 2022-06-07 13:51:42
...

getAction()getActionMasked()

getAction() 是以前的版本出来的

getActionMasked() 是为了多点触控, 现在用的话都选这个就好

shouldDelayChildPressedState()

自定义容器的时候, 如果不需要滚动, 那么需要重写 shouldDelayChildPressedState() , 并且返回 false , 这个方法如果要滚动的话, 会延迟 press 的状态

事件调用

正常情况下是

  • 父容器的 dispatchTouchEvent()

  • -> 父容器的 boolean result = onInterceptTouchEvent()

    • -> 如果 resulttrue , 那么会调用 父容器自己的 onTouchEvent()

    • 如果 resultfalse , 会调用子 ViewonTouchEvent

假设现在的需求是 RecyclerView , 某个 holder 里面的一个子 View 设置了点击事件
  • 当手指触摸到子 View 的时候父容器默认不拦截,

    • 如果手指直接抬起, 那么就响应子 View 的点击事件

    • 如果手指移动, 移动距离达到了设定的阈值, 那么 RecyclerView 的 onInterceptTouchEvent()return true , 把事件接管, 然后给子 View 一个 ACTION_CANCEL 事件

requestDisallowInterceptTouchEvent()

有的时候子 View 不想被父容器拦截事件, 就可以在 onTouchEvent()DOWN 事件的时候调用 parent.requestDisallowInterceptTouchEvent(true) 然后 return true

这样后续的 MOVE 事件就会一直到自己的 onTouchEvent(), 当达到一定条件自己不需要处理事件了调用 parent.requestDisallowInterceptTouchEvent(false)

这个时候如果父容器的 onInterceptTouchEvent() 返回了 true , 那么就会接收到一个 CANCEL 事件, 然后后续的事件也不会再有了

事件传递伪代码

open class TestView {

    open fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return onTouchEvent(ev)
    }

    open fun onTouchEvent(ev: MotionEvent): Boolean {
        return false
    }
}

open class TestViewGroup : TestView() {

    private var mChild: TestView? = null

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return if (onInterceptTouchEvent(ev)) {
            return onTouchEvent(ev)
        } else {
            mChild?.onTouchEvent(ev) ?: super.dispatchTouchEvent(ev)
        }
    }

    open fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return false
    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        return super.onTouchEvent(ev)
    }
}

class MLayout : TestViewGroup() {
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        return super.onTouchEvent(ev)
    }
}
相关标签: 自定义控件