android中的按键处理

来源:互联网 发布:java工程师资格证 编辑:程序博客网 时间:2024/05/16 06:59

转载自

http://venus585625.iteye.com/blog/907740


写的不错,比较深入,转贴于此


 在android中,所有的按键、触屏等事件,都是从顶至下进行分发的。每个ViewGroup子类对象会维持一个Focused变量。它表示在这个控件中具有Focused控件(此控件或是其子控件)。当有按键发生时 会沿着Focuse Path 找到RealFocus 控件(是真正Focused 控件,不是其子控件具有焦点)。同理触屏事件的分发也是如此,只不过和Focuse无关。父控件会遍历所有子控件,看看谁处于触碰事件,并分发给它。 

   如果Home key、Menu key,Back Key,Enter key事件(或许还有别的按键)(一些特殊功能的按键,声音等等)发生时 ,会产生一个FINISHED_EVENT 消息,是由InPutMethodManagerService通过AIDL进程调用产生 。 
在ViewRoot 中捕获。 

Java代码  收藏代码
  1. case FINISHED_EVENT:  
  2.      handleFinishedEvent(msg.arg1, msg.arg2 != 0);  
  3.      break;  
  4. d handleFinishedEvent(int seq, boolean handled) {  
  5.  final KeyEvent event = (KeyEvent)retrievePendingEvent(seq);  
  6.  if (DEBUG_IMF) Log.v(TAG, "IME finished event: seq=" + seq  
  7.          + " handled=" + handled + " event=" + event);  
  8.  if (event != null) {  
  9.      final boolean sendDone = seq >= 0;  
  10.      if (!handled) {  
  11.          deliverKeyEventToViewHierarchy(event, sendDone);  
  12.          return;  
  13.      } else if (sendDone) {  
  14.          if (LOCAL_LOGV) Log.v(  
  15.                  "ViewRoot""Telling window manager key is finished");  
  16.          try {  
  17.              sWindowSession.finishKey(mWindow);  
  18.          } catch (RemoteException e) {  
  19.          }  
  20.      } else {  
  21.          Log.w("ViewRoot""handleFinishedEvent(seq=" + seq  
  22.                  + " handled=" + handled + " ev=" + event  
  23.                  + ") neither delivering nor finishing key");  
  24.      }  
  25.  }  

   普通按键 发生时,产生DISPATCH_KEY_FROM_IME 消息 由ViewRoot捕获此消息 
Java代码  收藏代码
  1. case DISPATCH_KEY_FROM_IME: {  
  2.     if (LOCAL_LOGV) Log.v(  
  3.         "ViewRoot""Dispatching key "  
  4.         + msg.obj + " from IME to " + mView);  
  5.     KeyEvent event = (KeyEvent)msg.obj;  
  6.     if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {  
  7.         // The IME is trying to say this event is from the  
  8.         // system!  Bad bad bad!  
  9.         event = KeyEvent.changeFlags(event,  
  10.                 event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM);  
  11.     }  
  12.     deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);  
  13. break;  

上面两大类按键如果预先没有别处理,都会由deliverKeyEventToViewHierarchy(event, sendDone);进行分发。 

分发路径:PhoneWindow.DecorView dispatchKeyEvent----》Activity dispatchKeyEvent ----》Window superDispatchKeyEvent --->DecorView superDispatchKeyEvent-->Super dispatchKeyEvent,后续按着 Focus Path分发。如果上述分发中未被处理 
会执行Activity dispatchKeyEvent 中的如下代码: 
Java代码  收藏代码
  1. event.dispatch(this, decor != null  
  2.                 ? decor.getKeyDispatcherState() : nullthis);  

进一步调用Focus Path中的 View 的 onXXX方法。如果在这些回调方法中,按键未被处理,则进一步由 PhoneWindow.DecorView中dispatchKeyEvent方法的代码 
Java代码  收藏代码
  1. return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)  
  2.                     : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);  

处理了:volumn key ,back key 等等按键。 

了解了这些就可以游刃有余地截获按键事件。。 


“Home key”如果应用程序中没有截获,则最后调用 Activity 中的onBackPressed 
默认实现: 
Java代码  收藏代码
  1. /** 
  2.  * Called when the activity has detected the user's press of the back 
  3.  * key.  The default implementation simply finishes the current activity, 
  4.  * but you can override this to do whatever you want. 
  5.  */  
  6. public void onBackPressed() {  
  7.     finish();  
  8. }  

原创粉丝点击