【参考链接】

开发艺术探索

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

 

触摸[0] 触摸事件传递机制


1.      

涉及到的类和方法主要有

ViewGroup     dispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()

View                dispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()


触摸[0] 触摸事件传递机制

一般来说,在自定义View/ViewGroup的时候,不修改dispatchTouchEvent(),只重写onInterceptTouchEvent()(不保留super调用)和onTouchEvent()(保留super调用,如果需要响应OnLongClickListener/OnClickListener的话)

 

2.      

如果设置了OnTouchListener,则会先执行OnTouchListener。并且只有OnTouchListener返回false才会再执行onTouchEvent()

 

3.      

如果子View能够收到ACTION_DOWN但其OnTouchListener/onTouchEvent()返回了false,则其不会再收到后续的ACTION_MOVEACTION_UP等。

 

4.      

可以在子View/ViewGroupOnTouchListener/onTouchEvent()ACTION_DOWN中使用getParent().requestDisallowInterceptTouchEvent()来请求父ViewGroup不要中断传递后续的ACTION_MOVEACTION_UP等。(此时也不会执行父ViewGrouponInterceptTouchEvent()

注意这只有在子View/ViewGroup能够收到ACTION_DOWN的前提下才能起作用。

 

5

只有能够执行到Viewsuper.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;
   
}
}

 

相关文章: