MotionEvent和KeyEvent机制

触屏操作的理解:

最基本的操作类型:

1.down:手指按下

2.move:手指在屏幕上移动

3.up:手指从屏幕上离开

操作原理:

现在流行的触屏手机的屏幕都是电容屏,它是通过人体微小电流和屏幕之间的电流交互来感知触屏的操作。


2.Android事件处理的三个重要函数

Android事件分发机制主要由“事件分发”—>“事件拦截”—>“事件响应”这三步来进行逻辑控制的。本文也将从这三步对应的函数来分析。

2.1 事件分发:public boolean dispatchTouchEvent(MotionEvent ev)

当监听到有触发事件时,首先由Activity进行捕获,然后事件就进入事件分发的流程。Activity本身没有事件拦截,从而将事件传递给最外层的View的dispatchTouchEvent(MotionEvent ev)方法,该方法将对事件进行分发。

  • return true : View消费所有事件。
  • return false :停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,那么事件将被系统消费、处理。
  • super.dispatchTouchEvent(ev): 将事件交由本层的事件拦截onInterceptTouchEvent方法处理。
2.2 事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)
  • return true: 对事件拦截,交由本层的onTouchEvent进行处理。
  • return false: 不拦截,分发到子View,由子View的dispatchTouchEvent方法处理。
  • super.onInterceptTouchEvent(ev):默认表示事件拦截,交由本层的onTouchEvent进行处理。
2.3 事件响应:public boolean onTouchEvent(MotionEvent ev)
  • return true: 表示onTouchEvent处理完事件后消费了此次事件。如果
  • return false: 不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费。如果到最顶层View还是返回false,那么该事件不消费,将交由Activity的onTouchEvent进行处理。
  • return: super.onTouchEvent,不响应事件,结果与return返回false一样。
  1. 点击事件的分发过程如下:dispatchTouchEvent—>onTouchListener的OnTouch方法—>onTouchEvent—>onClickListener的onClick方法。从而也可以看出onTouch优先于onClick执行

android事件处理总体流程:

首先,Activity调用dispatchTouchEvent分发事件,将事件交给ViewGroup来处理,ViewGroup继续分发,同时也处理这个事件,如果事件处理返回true,就代表该事件被消费了,停止分发,反之,同理分发给View。当ViewGroup、View都没有消费时,就交给Activity消费。

MotionEvent和KeyEvent机制_第1张图片

如果onTouch()或者onTouchEvent()返回True,那么久会停止分发。 


我们来看一下View中dispatchTouchEvent方法的源码:

[java]  view plain  copy
  1. public boolean dispatchTouchEvent(MotionEvent event) {  
  2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
  3.             mOnTouchListener.onTouch(this, event)) {  
  4.         return true;  
  5.     }  
  6.     return onTouchEvent(event);  
  7. }  

首先是进行了一个判断,如果mOnTouchListener != null,(mViewFlags & ENABLED_MASK) == ENABLED和mOnTouchListener.onTouch(this, event)这三个条件都为真,就返回true,否则就去执行onTouchEvent(event)方法并返回。


先看一下第一个条件,mOnTouchListener这个变量是在哪里赋值的呢?我们寻找之后在View里发现了如下方法:

[java]  view plain  copy
  1. public void setOnTouchListener(OnTouchListener l) {  
  2.     mOnTouchListener = l;  
  3. }  

Bingo!找到了,mOnTouchListener正是在setOnTouchListener方法里赋值的,也就是说只要我们给控件注册了touch事件,mOnTouchListener就一定被赋值了。


第二个条件(mViewFlags & ENABLED_MASK) == ENABLED是判断当前点击的控件是否是enable的,按钮默认都是enable的,因此这个条件恒定为true。


第三个条件就比较关键了,mOnTouchListener.onTouch(this, event),其实也就是去回调控件注册touch事件时的onTouch方法。也就是说如果我们在onTouch方法里返回true,就会让这三个条件全部成立,从而整个方法直接返回true。如果我们在onTouch方法里返回false,就会再去执行onTouchEvent(event)方法。


dispatchTouchEvent返回值是onTouchEvent()的返回值,一般而言,它在ondispatchEvent内部总是返回true(可能不希望在onTouch()中就停止对ACTION的传递吧)。dispatchTouchEvent内部中还有一个方法就是onTouch(),如果onTouch()返回true,那么就不会执行下面的onTouchEvent()。总而言之,要想onTouchEvent()能够执行,在onTouch()中就必须返回false;要想ACTION能够继续分发,就必须使dispatchTouchEvent()返回值为true。


dispatchTouchEvent返回值的意义跟onTouch返回值的区别,两者返回true的时候ACTION都会传递到ACTION_DOWN,其中onTouch返回true的时候由于不会执行到onTouchEvent所以不会执行到onClick,dispatchTouchEvent返回值为true对会不会执行onClick没有影响;onTouch返回false的时候执行onTouchEvent,如果此时该控件是可点击的就发执行onClick,而dispatchTouchEvent返回false就停止ACTION传递。


onTouchEvent的源码比复杂,在这里只强调一点,onClick方法在onTouchEvent方法内部,所以说onTouch>onTouchEvent>onClick。

结合上面所讲,如果onTouch返回true,onClick就不会再执行了。

KeyEvent

1.KeyEvent

int ACTION_DOWN = 0:标记down的常量

int ACTION_UO = 1:标记up的常量

int getAction:得到事件的类型

int getKeyCode():得到按键的keycode(唯一标志)

startTracking():追踪事件,用于长按监听

2.Activity

 boolean dispatchKeyEvent(keyEvent event):分发事件

boolean onKeyDown(int keyCode,KeyEvent event):按下按键的回调

boolean onKeyUp(int keyCode,KeyEvent event):松开按键的回调

boolean onKeyLongPress(int keyCode,KeyEvent event):长按按键的回调

KeyEvent事件主要用途:比如点击返回按钮退出Activity(虽然这是系统已经实现好了的),然后实现OnKeyUp(),以实现在退出时,弹出一个对话框,提示是否退出。

MotionEvent和KeyEvent机制_第2张图片

更多精彩,请看:http://blog.csdn.net/guolin_blog/article/details/9097463

你可能感兴趣的:(android)