【参考链接】
开发艺术探索
AndroidView 事件分发机制 源码解析 (上)http://blog.csdn.net/lmj623565791/article/details/38960443
AndroidViewGroup事件分发机制http://blog.csdn.net/lmj623565791/article/details/39102591
探究requestDisallowInterceptTouchEvent失效的原因http://blog.csdn.net/jiwangkailai02/article/details/46666147
1.
涉及到的类和方法主要有
ViewGroup的 dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()
View的
dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()
一般来说,在自定义View/ViewGroup的时候,不修改dispatchTouchEvent(),只重写onInterceptTouchEvent()(不保留super调用)和onTouchEvent()(保留super调用,如果需要响应OnLongClickListener/OnClickListener的话)
2.
如果设置了OnTouchListener,则会先执行OnTouchListener。并且只有OnTouchListener返回false才会再执行onTouchEvent()。
3.
如果子View能够收到ACTION_DOWN但其OnTouchListener/onTouchEvent()返回了false,则其不会再收到后续的ACTION_MOVE、ACTION_UP等。
4.
可以在子View/ViewGroup的OnTouchListener/onTouchEvent()的ACTION_DOWN中使用getParent().requestDisallowInterceptTouchEvent()来请求父ViewGroup不要中断传递后续的ACTION_MOVE、ACTION_UP等。(此时也不会执行父ViewGroup的onInterceptTouchEvent())
注意这只有在子View/ViewGroup能够收到ACTION_DOWN的前提下才能起作用。
5、
只有能够执行到View的super.onTouchEvent()才能够触发onLongClickListener/onClickListener。
如果设置了onLongClickListener,在ACTION_DOWN超时后就会触发onLongClickListener。
只有当onLongClickListener返回false,在ACTION_UP后才会继续触发onClickListener。
可以使用如下的代码来修改验证
public class
MyFrameLayout
extends
FrameLayout {
//
public static final intACTION_DOWN = 0;
// public static finalint ACTION_UP = 1;
// public static finalint ACTION_MOVE = 2;
// public static finalint ACTION_CANCEL = 3;
public static final
String[]
ACTIONS={"ACTION_DOWN",
"ACTION_UP",
"ACTION_MOVE",
"ACTION_CANCEL"};
public MyFrameLayout(Context context)
{
super(context);
init();
}
public
MyFrameLayout(Context context,
AttributeSet attrs) {
super(context,
attrs);
init();
}
public
MyFrameLayout(Context context,
AttributeSet attrs, int
defStyle) {
super(context,
attrs,
defStyle);
init();
}
public void
init(){
setOnTouchListener(new
OnTouchListener() {
@Override
public boolean
onTouch(View view,
MotionEvent motionEvent) {
Log.e("shadowfaxghh",
"MyFrameLayout OnTouchListener "+ACTIONS[motionEvent.getAction()]);
return false;
}
});
setOnLongClickListener(new
OnLongClickListener() {
@Override
public boolean
onLongClick(View view) {
Log.e("shadowfaxghh",
"MyFrameLayout onLongClick");
return false;
}
});
setOnClickListener(new
OnClickListener() {
@Override
public void
onClick(View view) {
Log.e("shadowfaxghh",
"MyFrameLayout onClick");
}
});
}
@Override
public boolean
dispatchTouchEvent(MotionEvent ev) {
Log.e("shadowfaxghh",
"MyFrameLayout dispatchTouchEvent "+ACTIONS[ev.getAction()]);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean
onInterceptTouchEvent(MotionEvent ev) {
Log.e("shadowfaxghh",
"MyFrameLayout onInterceptTouchEvent "+ACTIONS[ev.getAction()]);
// return super.onInterceptTouchEvent(ev);
// return false;
switch
(ev.getAction()){
case
MotionEvent.ACTION_DOWN:
return false;
default:
return true;
}
}
@Override
public boolean
onTouchEvent(MotionEvent event) {
Log.e("shadowfaxghh",
"MyFrameLayout onTouchEvent "+ACTIONS[event.getAction()]);
super.onTouchEvent(event);//for
onLongClick/onClick
return true;
}
}
public class
MyTextView
extends
TextView {
public static final
String[]
ACTIONS={"ACTION_DOWN",
"ACTION_UP",
"ACTION_MOVE",
"ACTION_CANCEL"};
public MyTextView(Context context)
{
super(context);
init();
}
public
MyTextView(Context context,
AttributeSet attrs) {
super(context,
attrs);
init();
}
public
MyTextView(Context context,
AttributeSet attrs, int
defStyle) {
super(context,
attrs,
defStyle);
init();
}
public void
init(){
setOnTouchListener(new
OnTouchListener() {
@Override
public boolean
onTouch(View view,
MotionEvent motionEvent) {
Log.e("shadowfaxghh",
"MyTextView OnTouchListener "+ACTIONS[motionEvent.getAction()]);
return false;
}
});
setOnLongClickListener(new
OnLongClickListener() {
@Override
public boolean
onLongClick(View view) {
Log.e("shadowfaxghh",
"MyTextView onLongClick");
return false;
}
});
setOnClickListener(new
OnClickListener() {
@Override
public void
onClick(View view) {
Log.e("shadowfaxghh",
"MyTextView onClick");
}
});
}
@Override
public boolean
dispatchTouchEvent(MotionEvent ev) {
Log.e("shadowfaxghh",
"MyTextView dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//
@Override
// public booleanonInterceptTouchEvent(MotionEvent ev) {
//
// Log.e("shadowfaxghh", "MyTextViewonInterceptTouchEvent");
//
//// return super.onInterceptTouchEvent(ev);
// return false;
// }
@Override
public boolean
onTouchEvent(MotionEvent event) {
Log.e("shadowfaxghh",
"MyTextView onTouchEvent "+ACTIONS[event.getAction()]);
super.onTouchEvent(event);//for
onLongClick/onClick
switch(event.getAction()){
case
MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
break;
default:
break;
}
return true;
}
}