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
<strong> 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);
     }
} </strong>
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

 

 

 

 

 

 

二、

 

是否調用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

 

 

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

其中只  dispatchTouchEvent return false:
  

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

其中只 onInterceptTouchEvent  return false

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

     1)  
  •  

    是否調用super

    return

     

    dispatchTouchEvent

    super

    false

     

    onInterceptTouchEvent

    super

    false

     

    onTouchEvent

    super

    false

     

     

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

    2)

    1、

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return false:

    onTouchEvent return false;
      

    2、

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return true:

    onTouchEvent return false;
     

     

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

     

     

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

     

    3、

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return false:

    onTouchEvent return false;
     

     

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

     

    4、

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return false:

    onTouchEvent return true;
     

     

     

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

     

    5、

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return true:

    onTouchEvent return true;
     

     

     

    反正不會再向下傳遞,子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
      

    執行了Activity中LinearLayout的點擊事件

    7、子view onTouchEvent return 的是true

    dispatchTouchEvent return  true:

    onInterceptTouchEvent return false:

    onTouchEvent return true;//false
      


    沒有執行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进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值