touch分发

子View

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;
import android.widget.TextView;
 
public class MyTextView extends TextView {
 
     private static final String TAG = "內嵌TextView" ;
 
     public MyTextView(Context context, AttributeSet attrs) {
         super (context, attrs);
     }
     public MyTextView(Context context){
         super (context);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         // TODO Auto-generated method stub
         System.out.println( "TextView onTouchEvent Method is start&&" );
         if (MotionEvent.ACTION_DOWN == event.getAction()){
             Log.v(TAG + " onTouchEvent:" , "ACTION_DOWN" );
         } else if (MotionEvent.ACTION_MOVE == event.getAction()){
             Log.v(TAG + " onTouchEvent:" , "ACTION_MOVE" );
         } else {
             Log.v(TAG + " onTouchEvent:" , "ACTION_UP" );
         }
         return super .onTouchEvent(event);
     }
}
ViewGroup LinearLayout:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
 
public class MyLinearLayout1 extends LinearLayout{
 
     public MyLinearLayout1(Context context, AttributeSet attrs) {
         super (context, attrs);
         this .setBackgroundColor(Color.WHITE);
         
     }
     public MyLinearLayout1(Context context) {
         super (context);
         this .setBackgroundColor(Color.WHITE);
     }
     
     private String TAG = "第一层MyLinearLayout" ;
     
     
     //該方法是用來分發觸摸事件的,確切說,應該是過濾觸摸事件的,如果return false的话,只能接收到DOWN事件,之后的比如MOVE、UP事件不会再继续接收.
     
     @Override
     public boolean dispatchTouchEvent(MotionEvent event){
         System.out.println( "dispatchTouchEvent method is start **" );
         if (MotionEvent.ACTION_DOWN == event.getAction()){
             Log.v(TAG + "dispatchTouchEvent:" , "ACTION_DOWN" );
         } else if (MotionEvent.ACTION_MOVE == event.getAction()){
             Log.v(TAG + "dispatchTouchEvent:" , "ACTION_MOVE" );
         } else {
             Log.v(TAG + "dispatchTouchEvent:" , "ACTION_UP" );
         }
         super .dispatchTouchEvent(event);       
         return true ;
     }
 
     //該方法只會在dispatchTouchEvent調用了super.dispatchTouchEvent之後才會觸發。
     //默認return false 只有return false子View才能接收到触摸事件
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event){
         System.out.println( "onInterceptTouchEvent method is start##" );
         super .onInterceptTouchEvent(event);
 
         if (MotionEvent.ACTION_DOWN == event.getAction()){
             Log.v(TAG + "onInterceptTouchEvent:" , "ACTION_DOWN" );
         } else if (MotionEvent.ACTION_MOVE == event.getAction()){
             Log.v(TAG + "onInterceptTouchEvent:" , "ACTION_MOVE" );
         } else {
             Log.v(TAG + "onInterceptTouchEvent:" , "ACTION_UP" );
         }
         return false ;
     }
     //該方法是用來消耗觸摸事件的
     //默認return false。return true 的話,就表示該事件已經處理結束。
     @Override
     public boolean onTouchEvent(MotionEvent event){
         System.out.println( "onTouchEvent method is start>>" );
         super .onTouchEvent(event);
         if (MotionEvent.ACTION_DOWN == event.getAction()){
             Log.v(TAG + "onTouchEvent:" , "ACTION_DOWN" );
         } else if (MotionEvent.ACTION_MOVE == event.getAction()){
             Log.v(TAG + "onTouchEvent:" , "ACTION_MOVE" );
         } else {
             Log.v(TAG + "onTouchEvent:" , "ACTION_UP" );
         }
         return true ;
     }
}
xml
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< com.testtouchevent.MyLinearLayout1 xmlns:android = "http://schemas.android.com/apk/res/android"
     xmlns:tools = "http://schemas.android.com/tools"
     android:id = "@+id/am_linear"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     android:paddingBottom = "@dimen/activity_vertical_margin"
     android:paddingLeft = "@dimen/activity_horizontal_margin"
     android:paddingRight = "@dimen/activity_horizontal_margin"
     android:paddingTop = "@dimen/activity_vertical_margin"
     tools:context = ".MainActivity" >
 
     < com.testtouchevent.MyTextView
         android:id = "@+id/am_tv"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:text = "@string/hello_world"
         android:textSize = "50sp" />
 
com.testtouchevent.MyLinearLayout1 >


一、

 

是否調用super

return

 

dispatchTouchEvent

 

true

 

onInterceptTouchEvent

super

true

 

onTouchEvent

super

true

 

 

 

 

 

 

touch分发_第1张图片

二、

 

是否調用super

return

 

dispatchTouchEvent

 

false

 

onInterceptTouchEvent

super

true

 

onTouchEvent

super

true

 

 

也就是說如果dispatchTouchEvent返回的是false,就不在接收接下來一系列觸摸事件的處理了。而且沒調用super,也不會將event傳遞到另外兩個方法。

三、

 

是否調用super

return

 

dispatchTouchEvent

super

true

 

onInterceptTouchEvent

super

true

 

onTouchEvent

super

true

 

 
touch分发_第2张图片

调用了  dispatchTouchEvent方法中调用了 super.dispatchTouchEvent()后,另外的两个方法才得以调用。

其中只  dispatchTouchEvent return false:
  touch分发_第3张图片

同樣的不會處理down之後的事件,但是會將其給後面的兩個方法。

其中只 onInterceptTouchEvent  return false

touch分发_第4张图片

 四、在ViewGroup中添加子View,並且設置了onClick之後:

     1)  

 

是否調用super

return

 

dispatchTouchEvent

super

false

 

onInterceptTouchEvent

super

false

 

onTouchEvent

super

false

 

 

touch分发_第5张图片

只接收down事件。之後的就不會再接收了。也就沒有點擊事件的處理情況,因為點擊的處理實在up之後進行的

2)

1、

dispatchTouchEvent return  true:

onInterceptTouchEvent return false:

onTouchEvent return false;
  

touch分发_第6张图片

2、

dispatchTouchEvent return  true:

onInterceptTouchEvent return true:

onTouchEvent return false;
 

touch分发_第7张图片

 

可以看到事件沒有分發給子view,這時如果LinearLayout也有觸摸的處理事件的話,比如Click那麼:

 

touch分发_第8张图片

 

也就是說,LinearLayout會響應點擊事件

 

3、

dispatchTouchEvent return  true:

onInterceptTouchEvent return false:

onTouchEvent return false;
 

touch分发_第9张图片

 

相比較2例子而言,如果onInterceptTouchEvent return 的是false 那麼會先向下傳遞,最終TextView會得到事件的最終處理權。

 

4、

dispatchTouchEvent return  true:

onInterceptTouchEvent return false:

onTouchEvent return true;
 

 

touch分发_第10张图片

 

可見向下傳遞後,子View處理完Click事件後,點擊事件已經消耗,所以LinearLayout不會在有點擊事件的響應。

 

5、

dispatchTouchEvent return  true:

onInterceptTouchEvent return true:

onTouchEvent return true;
 

 

touch分发_第11张图片

 

反正不會再向下傳遞,子view獲取不到事件了,所以onTouchEvent返回什麼就沒什麼大的關係了。

上面的例子都是子View的onTouchEvent return super.onTouchEvent(event); 下面我們手動的改一下讓他return false or true

 

6、子view onTouchEvent  return 的是false

dispatchTouchEvent return  true:

onInterceptTouchEvent return false:

onTouchEvent return true;//false
  

touch分发_第12张图片

執行了Activity中LinearLayout的點擊事件

7、子view onTouchEvent return 的是true

dispatchTouchEvent return  true:

onInterceptTouchEvent return false:

onTouchEvent return true;//false
  

touch分发_第13张图片


沒有執行Activity中TextView的點擊事件。

总结

以上的几种情况就是我们经常遇到的了,总结起来有几个重要的点 :
1、如果Parent ViewGroup的onInterceptTouchEvent返回false, 并且触摸的目标view对于触摸事件的处理结果返回的是true,那么后续事件会先经过parent 的onInterceptTouchEvent, 然后再交给目标view进行处理;
2、如果Parent ViewGroup的onInterceptTouchEvent返回true,即对事件进行拦截,那么事件将不会再经过onInterceptTouchEvent,而是直接进入到onTouchEvent进行处理;如果onTouchEvent返回true,则表示该事件被处理了;如果返回FALSE,则代表事件没有被处理,那么事件会被上交给它的parent来处理,如果没有parent来处理,那么最终会交给Activity来处理;
3、如果用户在触摸的某个事件才拦截,那么目标view会收到一个CANCEL事件,然后后续的事件不会再交给目标view,而被转交给Parent的onTouchEvent方法进行处理。比如情景6当中,在TouchLayout的DOWN时不对事件进行拦截,这时事件会被TouchTv正常处理。但是在MOVE时事件被拦截了,此时TouchTv收到了一个CANCEL事件,MOVE以及后续的事件就交给了TouchLayout进行处理。

你可能感兴趣的:(touch分发)