Android事件的分发机制(Touch)
- 事件类型(4种):
| 事件类型 | 具体动作 |
|---|---|
| MotionEvent.ACTION_DOWN | 按下View(所有事件开始) |
| MotionEvent.ACTION_UP | 抬起View |
| MotionEvent.ACTION_MOVE | 滑动View |
| MotionEvent.ACTION_CANCEL | 结束事件 |
| MotionEvent.ACTION_MASK | 处理多点触控(ACTION_POINTER_UP,ACTION_POINTER_DOWN) |
一般都是由事件DOWN开始到事件UP结束,中间有无数个MOVE。
- 事件的分发即事件的传递
Activity->ViewGroup->View
dispathTouchEvent()->onInterceptTouchEvent()->onTouchEvent()
当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发
创建一个新的layout并重写onInterceptTouchEvent() 和onTouchEvent()
- 在
onInterceptTouchEvent()中拦截DOWN事件,如果检测到向下滑动View,return true(将事件分发给后面的OnTouchEvent())。 - 在
onTouchEvent()中的ACTION_DOWN动作中获得向下滑动的实时距离,并用function将header图片进行放大 - 在
onTouchEvent()中的ACTION_UP动作中使用恢复header图片的尺寸的function将下拉的图片弹回 - 在自定义的layout中,需要使用函数将header从
Activity传入Layout,在Activity中使用setHeader()函数将header的id传过来。
触摸方向冲突问题
-
当外部的
Layout截获了Touch事件后,内部的View将不再能够获取到处理View的Touch事件的权力,此时会出现触摸方向冲突问题:当手指按下屏幕并向下滑动,正常情况下应该是下拉回弹的动作,但此时如果没有松开手指而是往回拖动View并超过了原来View的初始位置时,View不再自动滚动,失去手指的控制能力。这是因为当触发了下拉回弹的动作条件时,该动作会被Layout的onTouchEvent()截获,而View的滚动是属于View本身的动作,不受Layout支配,这时要想办法将Layout的控制权交出给View。在
dispatchTouchEvent()使用一个Boolean来判断是否是第一次上拉动作,然后再在onTouchEvent()中的需要交出控制权的条件内部,创建一个新的TouchEvent并付给该View,使用dispatchTouchEvent(event)来付与View控制权,用return false将控制权从onTouchEvent()还回dispatchTouchEvent()。这样在检测到不应该被截获的动作时,动作权被交还给dispatchTouchEvent()。