View分发机制
点击事件的分发机制
1.点击事件(MotionEvent)
典型的时间类型:(MotionEvent.)
- ACTION_DOWN——手指刚刚接触屏幕
- ACTION_MOVE——手指在屏幕上移动
- ACTION_UP——手指离开屏幕的一瞬间
一系列点击事件:
- 点击屏幕后离开(没有移动):DOWN->UP
- 点击屏幕一会再离开:DOWN->MOVE->…->MOVE->UP
获取点击事件的x,y坐标:
1)getX()、getY():获取相对于当前View左上角x、y坐标。
2)getRawX()、getRawY():获取相对于手机屏幕左上角x和y坐标。
2.TouchSlop(顺便了解下,和View分发无关)
TouchSlop是系统所能识别出的被认为是滑动的最小距离。(它是一个常量)即小于此值系统将认为它没用滑动。
获取此常量的方法:ViewConfiguration.get(getContext()).getScaledTouchSlop()
源码定义在:frameworks/base/core/res/res/values/config.xml文件中“config_viewConfiguationTouchSlop”,值为8dp。
3.三个重要方法
public boolean dispatchTouchEvent(MotionEvent ev)
作用:进行事件的分发
什么时候调用:当事件传递到当前View时
返回值意义:是否消耗当前事件
注意:返回值受当前View的onTouchEvent和下级View的dispatchEvent影响。
public boolean onInterceptTouchEvent(MotionEvent event)
作用:判断是否拦截某个事件
什么时候调用:在上面那个方法内调用,若当前View拦截了某个事件,那么在同一个事件序列里,此方法不会再次被调用。
返回值意义:是否拦截当前事件。
public boolean onTouchEvent(MotionEvent event)
作用:处理点击事件
返回值意义:如果不消耗,则在同一个时间序列中,当前View无法再次接受到事件。
这三个方法的的关系:
伪代码:
public boolean dispatchTouchEvent(MotionEvent ev){
boolean consume = false;
if(onInterceptTouchEvent(ev)){
consume = onTouchEvent(ev)
}else{
consume = child.dispatchTouchEvent(ev);
}
}
理解:在当前View的dispatchTouchEvent方法中设置一个布尔量consume,表示是否消耗此事件,判断当前View是否拦截该事件,若拦截,consume有当前事件的onTouchEvent决定,否则,由子View的dispatchEvent决定。最后当前View的dispatchTouchEvent返回consume。
从中我们可以发现:事件分发是向下传递的:Activity->Window->View。