/**
* View的事件分发
*/
public class View{
public boolean dispatchTouchEvent(MotionEvent ev){
boolean result = false;
// 先判断是否设置了onTouchListener,如果设置了,就调用
if (mOnTouchListener != null && mOnTouchListener.onTouch(ev)) {
result = true;
}
// 如果没有设置onTouchListener,或者调用了onTouch后返回了false,那么就调用onTouchEvent
if (!result && onTouchEvent(ev)) {
result = true;
}
return result;
}
public boolean onTouchEvent(MotionEvent ev){
// 如果View可点击
if (isClickable()) {
switch (ev.getAction()) {
...
case MotionEvent.ACTION_UP:
...
// 判断是否设置了onClickListener,设置了就调用,并消耗事件
if (mOnClickListener != null) {
mOnClickListener.onClick(this);
}
...
break;
...
}
// 可点击的View,默认会消耗掉事件
return true;
}
// 不可点击的View,默认不消耗事件
return false;
}
}
/**
* ViewGroup的事件分发
*/
public class ViewGroup extends View{
// 一旦有子元素消耗了事件,这个子元素就被赋值给mFirstTouchTarget
public View mFirstTouchTarget = null;
public boolean dispatchTouchEvent(MotionEvent ev){
int action = ev.getAction();
boolean handled = false;
boolean intercepted;
// DOWN事件,或者有子元素消耗事件,则进入if语句内,判断是否拦截
if (action == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
// 取出 是否允许拦截 的标记,默认是false。子元素可以通过requestDisallowInterceptTouchEvent(true);将这个标记设置为true
boolean disallow = getFlagDisallowIntercept();
if (!disallow) {
// 允许拦截,调用onInterceptTouchEvent判断是否拦截
intercepted = onInterceptTouchEvent(ev);
}else {
// 不允许拦截,直接不拦截
intercepted = false;
}
}else {
// 非DOWN事件,或者没有子元素消耗了事件,直接拦截
intercepted = true;
}
// 如果有子元素消耗事件,alreadyDispatched就被赋值为true
boolean alreadyDispatched = false;
if (!intercepted) {
// 不拦截事件
// 遍历子元素
for (int i = 0 ; i < mChildList().size() ; i++) {
View child = mChildList.get(i);
float x = ev.getX();
float y = ev.getY();
if (x >= child.left && x <= child.right && y >= child.top && y <= child.bottom) {
// 事件位于子元素所在区域内,将事件分发给子元素
if (child.dispatchTouchEvent(ev)) {
// 子元素消耗了事件
mFirstTouchTarget = child;
alreadyDispatched = true;
// 跳出循环,不再分发
break;
}
}
}
}
if (mFirstTouchTarget == null) {
// 没有子元素消耗事件
// ViewGroup自行处理事件
super.dispatchTouchEvent(ev);
}else {
// 有子元素消耗了事件,则后续事件全部交给该子元素处理,不管他是否消耗事件
if (alreadyDispatched) {
mFirstTouchTarget.dispatchTouchEvent(ev);
handled = true;
}
}
return handled;
}
public boolean onTouchEvent(MotionEvent ev){
super.onTouchEvent(ev);
}
public boolean onInterceptTouchEvent(MotionEvent ev){
return false;
}
}