现在的位置: 首页 > 移动开发 > 正文

android 事件处理

2019年10月09日 移动开发 ⁄ 共 16242字 ⁄ 字号 评论关闭

用到的例子工程介绍:在viewGroup中加入子view,即LinerLayout中存在一子view,在MyLinerLayout中重写了 dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

在MyTestView中重写了dispatchTouchEvent、onTouchEvent。

分别研究各种返回值对事件传递的路径影响。

MyLinerLayout.java

  1. public class MyLinearLayout extends LinearLayout  implements View.OnClickListener,View.OnLongClickListener  {  
  2.     private final static String TAG = "TouchEvent";  
  3.     public MyLinearLayout(Context context, AttributeSet attrs) {  
  4.    
  5.         super(context, attrs);  
  6.         // TODO Auto-generated constructor stub  
  7.         Log.v(TAG , "MyLinearLayout");  
  8.         //this.setOnClickListener(this);  
  9.         //this.setOnLongClickListener(this);  
  10.     }  
  11.       
  12.     public void onClick(View v) {  
  13.         // TODO Auto-generated method stub  
  14.         Log.v(TAG ,  "MyLinearLayout onClick [" + "] test.................view:"+v.getId() );  
  15.     }  
  16.       
  17.     @Override  
  18.     public boolean onLongClick(View v) {  
  19.         // TODO Auto-generated method stub  
  20.         boolean b = true;  
  21.         Log.v(TAG ,  "MyLinearLayout onLongClick [" + "] test.................view:"+v.getId() +"return :"+b);  
  22.         return true;  
  23.     }  
  24.       
  25.     @Override  
  26.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  27.         int action = ev.getAction();  
  28.    
  29.         switch (action) {  
  30.    
  31.         case MotionEvent.ACTION_DOWN:  
  32.    
  33.             Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_DOWN");  
  34.    
  35.             break;  
  36.    
  37.         case MotionEvent.ACTION_MOVE:  
  38.    
  39.             Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_MOVE");  
  40.             return false;  
  41.             //break;  
  42.    
  43.         case MotionEvent.ACTION_UP:  
  44.    
  45.             Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_UP");  
  46.    
  47.             break;  
  48.    
  49.         case MotionEvent.ACTION_CANCEL:  
  50.    
  51.             Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_CANCEL");  
  52.    
  53.             break;  
  54.    
  55.         }  
  56. //          Log.v(TAG ,  "dispatchTouchEvent "+super.dispatchTouchEvent(ev));  
  57.         boolean b = super.dispatchTouchEvent(ev);  
  58.         //boolean b = false;  
  59.         Log.v(TAG ,  "MyLinearLayout --dispatchTouchEvent ["+action+ "] test.................return:"+b);  
  60.         return b;  
  61.     }  
  62.    
  63.     @Override  
  64.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  65.    
  66.         int action = ev.getAction();  
  67.    
  68.         switch (action) {  
  69.    
  70.         case MotionEvent.ACTION_DOWN:  
  71.    
  72.             Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_DOWN");  
  73.    
  74.             break;  
  75.    
  76.         case MotionEvent.ACTION_MOVE:  
  77.    
  78.             Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_MOVE");  
  79.    
  80.             break;  
  81.    
  82.         case MotionEvent.ACTION_UP:  
  83.    
  84.             Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_UP");  
  85.    
  86.             break;  
  87.    
  88.         case MotionEvent.ACTION_CANCEL:  
  89.    
  90.             Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_CANCEL");  
  91.    
  92.             break;  
  93.    
  94.         }  
  95.         //boolean b = super.onInterceptTouchEvent(ev);  
  96.         boolean b = true;  
  97.         Log.v(TAG ,  "MyLinearLayout --onInterceptTouchEvent ["+action+ "] test.................return: "+b);  
  98.         return b;  
  99.    
  100.     }  
  101.    
  102.     @Override  
  103.     public boolean onTouchEvent(MotionEvent ev) {  
  104.    
  105.         int action = ev.getAction();  
  106.         //boolean  b = super.onTouchEvent(ev);  
  107.         boolean b = true;  
  108.         switch (action) {  
  109.    
  110.         case MotionEvent.ACTION_DOWN:  
  111.    
  112.             Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_DOWN");  
  113.    
  114.             break;  
  115.    
  116.         case MotionEvent.ACTION_MOVE:  
  117.    
  118.             Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_MOVE");  
  119.    
  120.             break;  
  121.    
  122.         case MotionEvent.ACTION_UP:  
  123.    
  124.             Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_UP");  
  125.    
  126.             break;  
  127.    
  128.         case MotionEvent.ACTION_CANCEL:  
  129.    
  130.             Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_CANCEL");  
  131.    
  132.             break;  
  133.    
  134.         }  
  135.          
  136.         Log.v(TAG ,  "MyLinearLayout --onTouchEvent ["+action+ "] test.................return: "+b);  
  137.         return b;  
  138.     }  
  139.   
  140.   
  141. }  

  1. TextView.java  

  1. package com.lee.stony;  
  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.SimpleAdapter.ViewBinder;  
  8. import android.widget.TextView;  
  9. import android.view.View;  
  10.   
  11. public class MyTestView extends TextView{  
  12.    
  13.     public static final String TAG = "TouchEvent";  
  14.    
  15.     public MyTestView(Context context, AttributeSet attrs) {  
  16.    
  17.         super(context, attrs);  
  18.         // TODO Auto-generated constructor stub  
  19.         Log.v(TAG, "MyTestView");  
  20.         /*this.setOnClickListener(this); 
  21.         this.setOnLongClickListener(this);*/  
  22.     }  
  23.       
  24.     /*@Override 
  25.     public void onClick(View v) { 
  26.         // TODO Auto-generated method stub 
  27.         Log.v(TAG ,  "MyTestView onClick [" + "] test.................view:"+v.getId() ); 
  28.     } 
  29.      
  30.     @Override 
  31.     public boolean onLongClick(View v) { 
  32.         // TODO Auto-generated method stub 
  33.         boolean b = true; 
  34.         Log.v(TAG ,  "MyTestView onLongClick [" + "] test.................view:"+v.getId() +"return :"+b); 
  35.         return true; 
  36.     } 
  37. */  
  38.       
  39.     @Override  
  40.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  41.         int action = ev.getAction();  
  42.    
  43.         switch (action) {  
  44.    
  45.         case MotionEvent.ACTION_DOWN:  
  46.    
  47.             Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_DOWN");  
  48.    
  49.             break;  
  50.    
  51.         case MotionEvent.ACTION_MOVE:  
  52.    
  53.             Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_MOVE");  
  54.    
  55.             break;  
  56.    
  57.         case MotionEvent.ACTION_UP:  
  58.    
  59.             Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_UP");  
  60.    
  61.             break;  
  62.    
  63.         case MotionEvent.ACTION_CANCEL:  
  64.    
  65.             Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_CANCEL");  
  66.    
  67.             break;  
  68.    
  69.         }  
  70.         boolean b = super.dispatchTouchEvent(ev);  
  71.         //boolean b = true;  
  72.         Log.v(TAG ,  "MyTestView dispatchTouchEvent ["+action+ "] test.................return:"+b);  
  73.         return b;  
  74.     }  
  75.    
  76.     @Override  
  77.     public boolean onTouchEvent(MotionEvent ev) {  
  78.         boolean b = super.onTouchEvent(ev);  
  79.         int action = ev.getAction();  
  80.    
  81.         switch (action) {  
  82.    
  83.         case MotionEvent.ACTION_DOWN:  
  84.    
  85.             Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_DOWN");  
  86.    
  87.             break;  
  88.    
  89.         case MotionEvent.ACTION_MOVE:  
  90.    
  91.             Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_MOVE");  
  92.    
  93.             break;  
  94.    
  95.         case MotionEvent.ACTION_UP:  
  96.    
  97.             Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_UP");  
  98.    
  99.             break;  
  100.    
  101.         case MotionEvent.ACTION_CANCEL:  
  102.    
  103.             Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_CANCEL");  
  104.    
  105.             break;  
  106.    
  107.         }  
  108.           
  109.         //boolean b = true;  
  110.         Log.v(TAG ,  "MyTestView onTouchEvent ["+action+ "] test.................return:"+b);  
  111.         return b;  
  112.    
  113.     }  
  114.    
  115. }  

 

1、 android中用于事件处理的方法和类主要有如下几种:

onTouchEvent

onInterceptTouchEvent//在viewgroup才有的方法,用于分发子view

dispatchTouchEvent 

 

实现View.OnClickListener 的onClick

实现View.OnLongClickListener 的 onLongClick

实现View.OnTouchClickListener 的 onTouch

 

说明:在事件处理中,其实我们一般遇到事件有3中,分别是down、move、up,其中move事件在一个操作中(这里说的一个操作就是用户与屏幕的交互,即由down到up的动作序列)可能会发生多次,但是,我们认为一个动作序列会包含以上三种事件,因此,在事件处理中就是要处理好这个过程,而最重要的就是down事件,这是一个动作序列的起始,没有down谈不上后面的事件了。所以,我们把消耗down事件的类当做是这个动作序列的最终载体。

2、 各种返回值的含义和作用

(1)dispatchTouchEvent()

返回值

作用

True

继续接受动作序列中的后续事件,如move、move、up

False

不接受动作序列中的后续事件,因此本次后续操作不起作用,如:down后返回false,则move和up都不会被接受,只能接受下个动作。这里为什么特别指定的down事件呢,因为如果down返回true,说明后续事件会被传递于此,但是move返回false呢?哈哈,这个就不会影响了,因此说down才是关键

总结:此方法一般用于初步处理事件,因为动作是由此分发,所以通常会调用super.dispatchTouchEvent。这样就会继续调用onInterceptTouchEvent,再由onInterceptTouchEvent决定事件流向。

例子:

 

 

当在DispatchTouchEvent中调用了super.dispatchTouchEvent,则会继续向下执行到onInterceptTouchEvent方法。

 

(2)onInterceptTouchEvent():

返回值

作用

True

事件会传递到自己的onTouchEvent()

False

传递到下一个view的dispatchTouchEvent()

例子1:

方法

返回值

说明

 

MyLinerLayout

dispatchTouchEvent

True

调用super. dispatchTouchEvent

onInterceptTouchEvent

true

True 则调用自己的onTouchEvent

onTouchEvent

true

True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent

MyTestView

dispatchTouchEvent

True

这里因为MyLinerLayout. onInterceptTouchEvent返回true,因此不会传递于此

onTouchEvent

True

 

图:点击父和子view效果一样

说明:Down事件在MyLinerLayout.onInterceptTouchEvent()后返回true,则传递到onTouchEvent,当其返回true时,动作序列的后续事件不会再通过onInterceptTouchEvent了,而是在dispatchTouchEvent中直接传递于onTouchEvent。注意:此处点击MylinerLayout和MytestView效果一致。

 

例子2:

方法

返回值

说明

 

MyLinerLayout

dispatchTouchEvent

True

调用super. dispatchTouchEvent

onInterceptTouchEvent

False

False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent

onTouchEvent

true

True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent

MyTestView

dispatchTouchEvent

True

调用super. dispatchTouchEvent

onTouchEvent

True

 

 

图1:点击父view

说明:onInterceptTouchEvent返回false本应该传给下个子view的dispatchTouchEvent,但是,点击的是父view,因此不存在子view而直接传给自己的onTouchEvent,并且onTouchevent返回true,所以,后续事件不经过onInterceptTouchEvent(确定了自己要处理就不必再考虑如何分发给子view了)

图2:点击子view

说明:可以看到虽然MytestView.onTouchEvent接受并返回了true,事件还是需要经过MyLinerLayout.onInterceptTouchEvent(这是一个通道,分发给子view就要经过),

 

总结:onInterceptTouchEvent要做的就是确定事件传递到哪个子view,如果返回false,但是又没有子view处理(因为根本就没有点击到子view),就自己处理了,而自己在onTouchEvent处理的后续事件就不必经过onInterceptTouchEvent了,它是判断传递给子view的,都不是子view处理,就不用经过了。(以上说明,android事件处理机制中,明确谁要处理,确定后就会形成一条通道,后续事件就走这条通道吧)

 

 

 

注意:正常情况下dispatchTouchEvent会调用super. dispatchTouchEvent,并将其作为返回值,其实这会传递下一个接受者,让下个接受者处理并将最终的处理的返回值(在最后的onTouchEvent中,让其决定是否还需要接受后续动作序列)作为自己的返回值。而下个调用者即是onInterceptTouchEvent,不过它只是决定分发方向的,所以它的返回值对dispatchTouchEvent不影响,而onInterceptTouchEvent也可以调用super.
onInterceptTouchEvent,但是这总返回false,即总希望让子view来处理。一般不用

 

 

(2)onTouchEvent():

返回值

作用

True

事件由自己处理消耗,后续动作序列让其处理,因为在down事件时确定了路径,因此后续事件就不会迷路了

False

自己不消耗事件了,向上返回让其他来父view的onTouchEvent接受处理吧

例子3:

方法

返回值

说明

 

MyLinerLayout

dispatchTouchEvent

 

调用super. dispatchTouchEvent,根据不同的view的返回值会不同,不过此处总是返回false

onInterceptTouchEvent

False

False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent

onTouchEvent

False

False 则后续动作序列一般不发到此处(要看dispatchTouchEvent的返回值,如果其使用super. dispatchTouchEvent,会使用本方法的返回值,即false)。

MyTestView

dispatchTouchEvent

 

调用super. dispatchTouchEvent,也会返回false

onTouchEvent

False

 

 

图1:点击父view

说明:当传递到自己的onTouchEvent时,返回false,而dispatchTouchEvent也使用这返回值false,因此,本次操作的后续动作序列就不会再传递了,没有view处理后续的move、up。除非再次点击才会有事件传递,不过,结果跟上图一样,处理了down返回false就没下文了。

 

 图2:点击子view

说明:当事件流向MytestView.onTouchEvent时,返回了false,说明自己不处理了,让父view的onTouchEvent处理吧,而父view也返回false不处理,就继续向上抛,直到消失,当down事件没有被view确认处理,则后续动作序列也就不会再传递了。

 

例子4:跟例子3差不多,只是MyLinerLayout.onTouchEvent返回true

方法

返回值

说明

 

MyLinerLayout

dispatchTouchEvent

 

调用super. dispatchTouchEvent,根据不同的view的返回值会不同,不过此处总是返回false

onInterceptTouchEvent

False

False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent

onTouchEvent

True

True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent

MyTestView

dispatchTouchEvent

 

调用super. dispatchTouchEvent,也会返回false

onTouchEvent

False

事件没有被消耗,传给父view的onTouchEvent

注意:这里点击父view会跟例子2中图1一样,因为,事件根本没有传递到子view的机会。

图1:点击子view

说明:当到达MyTestView. onTouchEvent时返回false,则传递给父view的onTouchEvent,而其返回true,说明就让其处理吧,所以后续动作序列直接发到此处。

 

总结:onTouchEvent被认为是动作的最终处理的函数,不管是父view还是子view处理,只要onTouchEvent消耗了事件(返回true),则认为后续动作序列的通路已经确定,否则,向上处理,直到消失。

 

3、前面说的都是在view或viewgroup的重写的处理事件的方法,但是,如果注册了监听器后事件又是如何走呢?

【上篇】
【下篇】

抱歉!评论已关闭.