Android View的事件分发

来源:互联网 发布:flux软件怎么用 编辑:程序博客网 时间:2024/05/16 17:15

1、案例

为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~

MyButton

[java] view plain copy
  1. package com.example.zhy_event03;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.util.Log;  
  6. import android.view.MotionEvent;  
  7. import android.widget.Button;  
  8.   
  9. public class MyButton extends Button  
  10. {  
  11.     private static final String TAG = MyButton.class.getSimpleName();  
  12.   
  13.     public MyButton(Context context, AttributeSet attrs)  
  14.     {  
  15.         super(context, attrs);  
  16.     }  
  17.   
  18.     @Override  
  19.     public boolean onTouchEvent(MotionEvent event)  
  20.     {  
  21.         int action = event.getAction();  
  22.   
  23.         switch (action)  
  24.         {  
  25.         case MotionEvent.ACTION_DOWN:  
  26.             Log.e(TAG, "onTouchEvent ACTION_DOWN");  
  27.             break;  
  28.         case MotionEvent.ACTION_MOVE:  
  29.             Log.e(TAG, "onTouchEvent ACTION_MOVE");  
  30.             break;  
  31.         case MotionEvent.ACTION_UP:  
  32.             Log.e(TAG, "onTouchEvent ACTION_UP");  
  33.             break;  
  34.         default:  
  35.             break;  
  36.         }  
  37.         return super.onTouchEvent(event);  
  38.     }  
  39.       
  40.     @Override  
  41.     public boolean dispatchTouchEvent(MotionEvent event)  
  42.     {  
  43.         int action = event.getAction();  
  44.   
  45.         switch (action)  
  46.         {  
  47.         case MotionEvent.ACTION_DOWN:  
  48.             Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");  
  49.             break;  
  50.         case MotionEvent.ACTION_MOVE:  
  51.             Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");  
  52.             break;  
  53.         case MotionEvent.ACTION_UP:  
  54.             Log.e(TAG, "dispatchTouchEvent ACTION_UP");  
  55.             break;  
  56.   
  57.         default:  
  58.             break;  
  59.         }  
  60.         return super.dispatchTouchEvent(event);  
  61.     }  
  62.   
  63.       
  64. }  

在onTouchEvent和dispatchTouchEvent中打印了日志~

然后把我们自定义的按钮加到主布局文件中;

布局文件:

[html] view plain copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context=".MainActivity" >  
  6.   
  7.     <com.example.zhy_event03.MyButton  
  8.         android:id="@+id/id_btn"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:text="click me" />  
  12.   
  13. </LinearLayout>  

最后看一眼MainActivity的代码

[java] view plain copy
  1. package com.example.zhy_event03;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.MotionEvent;  
  7. import android.view.View;  
  8. import android.view.View.OnTouchListener;  
  9. import android.widget.Button;  
  10.   
  11. public class MainActivity extends Activity  
  12. {  
  13.     protected static final String TAG = "MyButton";  
  14.     private MyButtonmButton ;  
  15.     @Override  
  16.     protected void onCreate(Bundle savedInstanceState)  
  17.     {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.           
  21.         mButton = (MyButton) findViewById(R.id.id_btn);  
  22.         mButton.setOnTouchListener(new OnTouchListener()  
  23.         {  
  24.             @Override  
  25.             public boolean onTouch(View v, MotionEvent event)  
  26.             {  
  27.                 int action = event.getAction();  
  28.   
  29.                 switch (action)  
  30.                 {  
  31.                 case MotionEvent.ACTION_DOWN:  
  32.                     Log.e(TAG, "onTouch ACTION_DOWN");  
  33.                     break;  
  34.                 case MotionEvent.ACTION_MOVE:  
  35.                     Log.e(TAG, "onTouch ACTION_MOVE");  
  36.                     break;  
  37.                 case MotionEvent.ACTION_UP:  
  38.                     Log.e(TAG, "onTouch ACTION_UP");  
  39.                     break;  
  40.                 default:  
  41.                     break;  
  42.                 }  
  43.                   
  44.                 return false;  
  45.             }  
  46.         });  
  47.     }  
  48.   
  49.       
  50. }  

在MainActivity中,我们还给MyButton设置了OnTouchListener这个监听~

好了,跟View事件相关一般就这三个地方了,一个onTouchEvent,一个dispatchTouchEvent,一个setOnTouchListener;

下面我们运行,然后点击按钮,查看日志输出:

[html] view plain copy
  1. 08-31 06:09:39.030: E/MyButton(879): dispatchTouchEvent ACTION_DOWN  
  2. 08-31 06:09:39.030: E/MyButton(879): onTouch ACTION_DOWN  
  3. 08-31 06:09:39.049: E/MyButton(879): onTouchEvent ACTION_DOWN  
  4. 08-31 06:09:39.138: E/MyButton(879): dispatchTouchEvent ACTION_MOVE  
  5. 08-31 06:09:39.138: E/MyButton(879): onTouch ACTION_MOVE  
  6. 08-31 06:09:39.147: E/MyButton(879): onTouchEvent ACTION_MOVE  
  7. 08-31 06:09:39.232: E/MyButton(879): dispatchTouchEvent ACTION_UP  
  8. 08-31 06:09:39.248: E/MyButton(879): onTouch ACTION_UP  
  9. 08-31 06:09:39.248: E/MyButton(879): onTouchEvent ACTION_UP  

我有意点击的时候蹭了一下,不然不会触发MOVE,手抖可能会打印一堆MOVE的日志~~~

好了,可以看到,不管是DOWN,MOVE,UP都会按照下面的顺序执行:

1、dispatchTouchEvent

2、 setOnTouchListener的onTouch

3、onTouchEvent

下面就跟随日志的脚步开始源码的探索

首先判断mOnTouchListener不为null,如果return true就不会有onTouchEvent事件了

OnTouchListen>onTouchEvent>OnClickListen。点击事件是最后执行的

总结整个View的事件转发流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent

在dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent到OnClickListen


1 0