您的位置:首页 > 移动开发 > Android开发

Android事件处理

2016-03-17 18:33 465 查看
用到的例子工程介绍:在viewGroup中加入子view,即LinerLayout中存在一子view,在MyLinerLayout中重写了 dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

在MyTestView中重写了dispatchTouchEvent、onTouchEvent。

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

MyLinerLayout.java

[java]
view plain
copy

public class MyLinearLayout extends LinearLayout  implements View.OnClickListener,View.OnLongClickListener  {  
    private final static String TAG = "TouchEvent";  
    public MyLinearLayout(Context context, AttributeSet attrs) {  
   
        super(context, attrs);  
        // TODO Auto-generated constructor stub  
        Log.v(TAG , "MyLinearLayout");  
        //this.setOnClickListener(this);  
        //this.setOnLongClickListener(this);  
    }  
      
    public void onClick(View v) {  
        // TODO Auto-generated method stub  
        Log.v(TAG ,  "MyLinearLayout onClick [" + "] test.................view:"+v.getId() );  
    }  
      
    @Override  
    public boolean onLongClick(View v) {  
        // TODO Auto-generated method stub  
        boolean b = true;  
        Log.v(TAG ,  "MyLinearLayout onLongClick [" + "] test.................view:"+v.getId() +"return :"+b);  
        return true;  
    }  
      
    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
        int action = ev.getAction();  
   
        switch (action) {  
   
        case MotionEvent.ACTION_DOWN:  
   
            Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_DOWN");  
   
            break;  
   
        case MotionEvent.ACTION_MOVE:  
   
            Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_MOVE");  
            return false;  
            //break;  
   
        case MotionEvent.ACTION_UP:  
   
            Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_UP");  
   
            break;  
   
        case MotionEvent.ACTION_CANCEL:  
   
            Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_CANCEL");  
   
            break;  
   
        }  
//          Log.v(TAG ,  "dispatchTouchEvent "+super.dispatchTouchEvent(ev));  
        boolean b = super.dispatchTouchEvent(ev);  
        //boolean b = false;  
        Log.v(TAG ,  "MyLinearLayout --dispatchTouchEvent ["+action+ "] test.................return:"+b);  
        return b;  
    }  
   
    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
   
        int action = ev.getAction();  
   
        switch (action) {  
   
        case MotionEvent.ACTION_DOWN:  
   
            Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_DOWN");  
   
            break;  
   
        case MotionEvent.ACTION_MOVE:  
   
            Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_MOVE");  
   
            break;  
   
        case MotionEvent.ACTION_UP:  
   
            Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_UP");  
   
            break;  
   
        case MotionEvent.ACTION_CANCEL:  
   
            Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_CANCEL");  
   
            break;  
   
        }  
        //boolean b = super.onInterceptTouchEvent(ev);  
        boolean b = true;  
        Log.v(TAG ,  "MyLinearLayout --onInterceptTouchEvent ["+action+ "] test.................return: "+b);  
        return b;  
   
    }  
   
    @Override  
    public boolean onTouchEvent(MotionEvent ev) {  
   
        int action = ev.getAction();  
        //boolean  b = super.onTouchEvent(ev);  
        boolean b = true;  
        switch (action) {  
   
        case MotionEvent.ACTION_DOWN:  
   
            Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_DOWN");  
   
            break;  
   
        case MotionEvent.ACTION_MOVE:  
   
            Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_MOVE");  
   
            break;  
   
        case MotionEvent.ACTION_UP:  
   
            Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_UP");  
   
            break;  
   
        case MotionEvent.ACTION_CANCEL:  
   
            Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_CANCEL");  
   
            break;  
   
        }  
         
        Log.v(TAG ,  "MyLinearLayout --onTouchEvent ["+action+ "] test.................return: "+b);  
        return b;  
    }  
  
  
}  

[java]
view plain
copy

TextView.java  

[java]
view plain
copy

package com.lee.stony;  
   
import android.content.Context;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.MotionEvent;  
import android.widget.SimpleAdapter.ViewBinder;  
import android.widget.TextView;  
import android.view.View;  
  
public class MyTestView extends TextView{  
   
    public static final String TAG = "TouchEvent";  
   
    public MyTestView(Context context, AttributeSet attrs) {  
   
        super(context, attrs);  
        // TODO Auto-generated constructor stub  
        Log.v(TAG, "MyTestView");  
        /*this.setOnClickListener(this); 
        this.setOnLongClickListener(this);*/  
    }  
      
    /*@Override 
    public void onClick(View v) { 
        // TODO Auto-generated method stub 
        Log.v(TAG ,  "MyTestView onClick [" + "] test.................view:"+v.getId() ); 
    } 
     
    @Override 
    public boolean onLongClick(View v) { 
        // TODO Auto-generated method stub 
        boolean b = true; 
        Log.v(TAG ,  "MyTestView onLongClick [" + "] test.................view:"+v.getId() +"return :"+b); 
        return true; 
    } 
*/  
      
    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
        int action = ev.getAction();  
   
        switch (action) {  
   
        case MotionEvent.ACTION_DOWN:  
   
            Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_DOWN");  
   
            break;  
   
        case MotionEvent.ACTION_MOVE:  
   
            Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_MOVE");  
   
            break;  
   
        case MotionEvent.ACTION_UP:  
   
            Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_UP");  
   
            break;  
   
        case MotionEvent.ACTION_CANCEL:  
   
            Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_CANCEL");  
   
            break;  
   
        }  
        boolean b = super.dispatchTouchEvent(ev);  
        //boolean b = true;  
        Log.v(TAG ,  "MyTestView dispatchTouchEvent ["+action+ "] test.................return:"+b);  
        return b;  
    }  
   
    @Override  
    public boolean onTouchEvent(MotionEvent ev) {  
        boolean b = super.onTouchEvent(ev);  
        int action = ev.getAction();  
   
        switch (action) {  
   
        case MotionEvent.ACTION_DOWN:  
   
            Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_DOWN");  
   
            break;  
   
        case MotionEvent.ACTION_MOVE:  
   
            Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_MOVE");  
   
            break;  
   
        case MotionEvent.ACTION_UP:  
   
            Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_UP");  
   
            break;  
   
        case MotionEvent.ACTION_CANCEL:  
   
            Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_CANCEL");  
   
            break;  
   
        }  
          
        //boolean b = true;  
        Log.v(TAG ,  "MyTestView onTouchEvent ["+action+ "] test.................return:"+b);  
        return b;  
   
    }  
   
}  



 

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的重写的处理事件的方法,但是,如果注册了监听器后事件又是如何走呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android事件处理