自定义View 自定义View 触摸反馈

自定义View的触摸反馈

重写onTouchEvent(),在方法内部定制触摸反馈算法
是否取消事件取决于ACTION_DOWN事件或PONITER_DOWN事件是否返回true
MotionEvent
        getActionMasked()和getAction()
        POINTER_DOWN / POINTER_UP 和 getActionIndex()

onTouchEvent()

    当用户按下(ACTION_DOWN)
        如果不在滑动控件中,切换至按下状态,并注册长按计时器
        如果在滑动控件中,切换至按下状态,并注册按下计时器
    当进入按下状态并移动(ACTION_MOVE)
        重绘Ripple Effect
        如果移动出自己的范围,自我标记本次事件失效,忽略后续事件
    当用户抬起(ACTION_UP)
        如果是按下状态并且未触发长按,切换至抬起状态并触发点击事件,并清除一切状态
        如果已经触发长按,切换至抬起状态并清除一切状态
    当事件意外结束(ACTION_CANCEL)
        切换至抬起状态,并清除一切状态

自定义ViewGroup 的触摸反馈

    除了重写onTouchEvent(),还需要重写onInterceptEvent()
    onInterceptEvent() 不用在第一时间返回true,而是在任意事件,需要拦截的时候返回true就行

触摸反馈的流程

    Activity.dispatchEvent()
        递归:ViewGroup(View).dispatchTouchEvent()
            ViewGroup.onInterceptTouchEvent()
            ViewGroup.onIntercepTouchEvent()
            Child.dispatchTouchEvent()
            Super.dispatchEvent()
                View.onTouchEvent()
        Activity.onTouchEvent()

View.dispatchTouchEvent()

        如果设置了OnTouchListener,调用OnTouchListener.onTouch()
            如果OnTouchListener消费了事件,返回true
            如果onTouchListener没有了消费事件,继续调用自己的onTouchEvent(),并返回和onTouchEvent()相同的结果
        如果没有设置onTouchEvent,同上

ViewGroup.dispatchEvent()

        如果是用户初次按下(ACTION_DOWN),清空TouchTargets和DISALLOW_INTERCEPT标记
        拦截处理
        如果不拦截并且不是CANCEL事件,并且是DOWN或者POINTER_DOWN,尝试把pointer(手指)通过TouchTarget分配给子View;并且如果分配给了新的子View,调用child.dispathTouchEvent()把事件传递给子View
        看有没有TouchTarget
            如果没有TouchTarget,调用自己的super.dispatchTouchEvent()
            如果有,调用child.dispatchEvent()把事件传给对应的子View(如果有的话)
            如果是POINTER_UP,从TouchTargets中清除POINTER信息,如果是UP或CANCEL,重置状态

TouchTarget

        作用:记录每个子View是被哪些pointer(手指)按下的
        结构:单向链表

拦截处理

        如果不是初次按下,并且没有TouchTarget,直接拦截
        如果不是初次按下,或者有TouchTarget
            如果设置了disallow intercept,不拦截

否则,调用onInterceptTouchEvent(),如果返回true则拦截,返回false则不拦截

你可能感兴趣的:(自定义View 自定义View 触摸反馈)