触摸事件学习系列文章详见:
在第一篇文章中又点击事件的一个例如引入事件的学习,之后第二篇文章查找一下点击事件最终是在什么地方触发的,发现是在onTouchEvent方法中,第三篇和第四篇总结了一下onTouchEvent的参数MotionEvent对象的常用属性getAction() 与 getX(), getY()。
前几篇是打下基础,现在可以基于这些知识分析下View.onTouchEvent也就是之前第二篇文章中查找到的发现点击事件触发的地方,View类是所有视图的基类,也就是如果子类不覆写此方法的话,触屏事件都是交由View.onTouchEvent处理。
分析的源码是Andorid 4.0 (Android 14)原因之前也解释过,这种通过的功能因为各种版本变化不会太大,View.onTouchEvent有130行肯定不会直接粘贴到blog上然后一行行的解释是什么意思,打算按照先总后分的形式整理。这篇文章并不是我想写这么长,实在是方法本身源码就很多,。
一、onTouchEvent整体结构
/**
* Implement this method to handle touch screen motion events.
*
* @param event The motion event.
* @return True if the event was handled, false otherwise.
*/
public boolean onTouchEvent(MotionEvent event) {
final int viewFlags = mViewFlags;
// 当前视图处于禁用状态
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
// 如果抬起手指清除掉按下状态
mPrivateFlags &= ~PRESSED;
// 当前显示还是按下状态,所以重刷一下
refreshDrawableState();
}
// 应该是当前视图处理当前触摸事件的,但是因为指定为禁用状态,
// 所以还是消耗当前事件,只是不做任何处理。
// 这样处理符合逻辑,因为用户当前触摸的是这个视图,虽然被设置为不触发任何处理。
// A disabled view that is clickable still consumes the touch
// events, it just doesn't respond to them.
return (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
}
// 把当前视图的事件交由其他视图处理。
if (mTouchDelegate != null) {
// 事件虽然传递给了当前视图,
// 但是如果其他视图通过设置mTouchDelegate增大触摸区域
// 并且当前触摸点在其他视图的扩大区域内。
if (mTouchDelegate.onTouchEvent(event)) {
// 交由扩大触摸区域的那个视图处理
// 并消耗此次触摸事件
return true;
}
}
// 如果当前视图是点击或者长按状态
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
// 点击与长按重要处理的地方,之后着重分析这块
......
}
// 是点击或者长按,当前方法反馈与处理用户操作
return true;
}
// 当前视图不处理