ViewGroup的相关事件有三个:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent(继承了View)。
View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。
Android 4.2.2源码 View 的事件分发机制
View.dispatchTouchEvent -> View.setOnTouchListener-> View.onTouchEvent (使用到了OnLongClickListener,onClickListener)
public boolean dispatchTouchEvent(MotionEvent event)方法内部处理过程:
(1) 判断方法 onFilterTouchEventForSecurity()返回值,其内部处理是: 如果窗口被遮蔽了就返回false,否则返回true
(2) 方法返回false,说明窗口被遮蔽了,整个dispatchTouchEvent返回false
(3) 方法返回true,说明窗口没有被遮蔽,则继续(4)
(4) 如果 mOnTouchListener不为空,且view的enable状态是可用,且mOnTouchListener的onTouch返回true,则整个 dispatchTouchEvent方法返回true
(5) 否则touch事件交给View的onTouchEvent方法处理:
View的public boolean onTouchEvent(MotionEvent event)方法内部处理过程
(1) 如果view的状态是DISABLED 则直接返回
(2) 否则继续判断mTouchDelegate(触摸代表)是否为空
(3) 如果mTouchDelegate(视图的点击区域(增大或者缩小可点击区域)) 不为空且mTouchDelegate.onTouchEvent返回true,则整个onTouchEvent方法返回true
(4) 否则继续以下的判断View的clickable或long_clickable,如果其中一个为true,则对MotionEvent进行分析处理:
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE))
{
....
swtich(event.getAction())
{
case ACTION_MOVE:
//如果触摸点不在当前视图内(手指移出了视图区域),则移除还没有执行的长按与轻触检测
//移除按下状态,移除后刷新视图
break;
case ACTION_DOWN:
//设置 mHasPerformedLongPress = false
//500ms后执行PerformClick()->OnLongClickListener,
//如果onLongClickListener的onLongClick(View v)返回true,则 mHasPerformedLongPress=true,否则mHasPerformedLongPress依然是false
break;
case ACTION_UP:
//当前是按下的状态,如果 mHasPerformedLongPress=false(长按事件没有发生OnLongClickListener为空或onLongClickListener返回false),
则执行public boolean PerformClick()方法,此方法内处理:如果onClickListener不为空则执行onClickListener并返回true
break;
case ACTION_CANCEL:
break;
}
return true;
}
注意点:
如果对一个View同时设置了OnLongClickListener和onClickListener,
那么 如果OnLongClickListener中的onClick方法返回false,则 onClickListener会被执行的,
如果OnLongClickListener中的onClick方法返回true, 则 onClickListener不会被执行的。