View Touch源码解析
2017-09-09 本文已影响0人
dengzi_android
1、现象分析
// 1、在自定义view中添加下面两个方法
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("dengzi", "dispatchTouchEvent." + getActionStr(event));
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("dengzi", "onTouchEvent." + getActionStr(event));
return super.onTouchEvent(event);
}
// 2、在使用自定义view的地方添加两个listener
customView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("dengzi", "OnTouchListener." + getActionStr(event));
return false;
}
});
customView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("dengzi", "onClick");
}
});
// 其中getActionStr()方法就是获取一下当前event的状态
private String getActionStr(MotionEvent event){
return event.getAction() == MotionEvent.ACTION_DOWN ? "Down"
: event.getAction() == MotionEvent.ACTION_MOVE ? "Move"
: event.getAction() == MotionEvent.ACTION_UP ? "Up" : "";
}
现象一:就是上面的代码,直接运行看log日志
-> dispatchTouchEvent.Down -> OnTouchListener.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up -> onTouchEvent.Up
-> onClick
现象二:原始代码中OnTouchListener 中更改 : return true; ,运行看log日志
-> dispatchTouchEvent.Down -> OnTouchListener.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up
现象三:原始代码中onTouchEvent 中更改 : return true; ,运行看log日志
-> dispatchTouchEvent.Down -> OnTouchListener.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up -> onTouchEvent.Up
现象四:原始代码中dispatchTouchEvent中更改 : return true; ,运行看log日志
-> dispatchTouchEvent.Down
-> dispatchTouchEvent.Move
-> dispatchTouchEvent.Up
现象五:原始代码中删除OnTouchListener ,运行看log日志
-> dispatchTouchEvent.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> onTouchEvent.Up
-> onClick
现象六:原始代码中删除OnTouchListener ,并且onTouchEvent 中更改 : return true; 运行看log日志
-> dispatchTouchEvent.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> onTouchEvent.Up
现象七:原始代码中删除OnTouchListener ,并且onTouchEvent 中更改 : return false; 运行看log日志
-> dispatchTouchEvent.Down
-> onTouchEvent.Down
2、源码分析(android-25)
首先来看dispatchTouchEvent(event) 方法
public boolean dispatchTouchEvent(MotionEvent event) {
// ...
// 初始化result 为 false
boolean result = false;
// ...
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// 如果是Down,则停止一切滑动事件
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
// ...
// ListenerInfo中存放着当前view的所有Listener事件
ListenerInfo li = mListenerInfo;
if (li != null // 当前view有设置Listener事件
&& li.mOnTouchListener != null // 当前view有设置OnTouchListener事件
&& (mViewFlags & ENABLED_MASK) == ENABLED // 当前view为Enabled状态
&& li.mOnTouchListener.onTouch(this, event)) { // 当前view设置的OnTouchListener事件中返回true
result = true; // result 置为 true
}
// 如果resut为false,则去调用onTouchEvent(),如果onTouchEvent()返回true,则将result 置为 true
// 如果resut为true,则不调用onTouchEvent()。
if (!result && onTouchEvent(event)) {
result = true;
}
}
// ...
return result;
}
接着来看onTouchEvent(event) 方法
public boolean onTouchEvent(MotionEvent event) {
// ...
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
(viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
switch (action) {
case MotionEvent.ACTION_UP:
// ...
// 设置点击事件
performClick();
// ...
break;
case MotionEvent.ACTION_DOWN:
// 初化touch相当信息
break;
case MotionEvent.ACTION_CANCEL:
// 将touch信息置为null
break;
case MotionEvent.ACTION_MOVE:
// 移动相关
break;
}
return true;
}
return false;
}
我们再来看performClick() 方法
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
// ...
// 设置当前view的点击事件
li.mOnClickListener.onClick(this);
}
return result;
}
3、总结一下
20160601225357520.jpg