转载自

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. caseFINISHED_EVENT:
  2. handleFinishedEvent(msg.arg1,msg.arg2!=0);
  3. break;
  4. dhandleFinishedEvent(intseq,booleanhandled){
  5. finalKeyEventevent=(KeyEvent)retrievePendingEvent(seq);
  6. if(DEBUG_IMF)Log.v(TAG,"IMEfinishedevent:seq="+seq
  7. +"handled="+handled+"event="+event);
  8. if(event!=null){
  9. finalbooleansendDone=seq>=0;
  10. if(!handled){
  11. deliverKeyEventToViewHierarchy(event,sendDone);
  12. return;
  13. }elseif(sendDone){
  14. if(LOCAL_LOGV)Log.v(
  15. "ViewRoot","Tellingwindowmanagerkeyisfinished");
  16. try{
  17. sWindowSession.finishKey(mWindow);
  18. }catch(RemoteExceptione){
  19. }
  20. }else{
  21. Log.w("ViewRoot","handleFinishedEvent(seq="+seq
  22. +"handled="+handled+"ev="+event
  23. +")neitherdeliveringnorfinishingkey");
  24. }
  25. }

普通按键 发生时,产生DISPATCH_KEY_FROM_IME 消息 由ViewRoot捕获此消息
Java代码
  1. caseDISPATCH_KEY_FROM_IME:{
  2. if(LOCAL_LOGV)Log.v(
  3. "ViewRoot","Dispatchingkey"
  4. +msg.obj+"fromIMEto"+mView);
  5. KeyEventevent=(KeyEvent)msg.obj;
  6. if((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM)!=0){
  7. //TheIMEistryingtosaythiseventisfromthe
  8. //system!Badbadbad!
  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():null,this);

进一步调用Focus Path中的 View 的 onXXX方法。如果在这些回调方法中,按键未被处理,则进一步由 PhoneWindow.DecorView中dispatchKeyEvent方法的代码
Java代码
  1. returnisDown?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. *Calledwhentheactivityhasdetectedtheuser'spressoftheback
  3. *key.Thedefaultimplementationsimplyfinishesthecurrentactivity,
  4. *butyoucanoverridethistodowhateveryouwant.
  5. */
  6. publicvoidonBackPressed(){
  7. finish();
  8. }

更多相关文章

  1. 写一个Android输入法01——最简步骤
  2. Delphi XE5 for Android(安卓)(十)
  3. android GPS开启方法 代码
  4. Android中的悬浮对话框和即点即关对话框
  5. android 一个有漂亮动画效果的Dialog
  6. 通用代码库之listview和GridView
  7. android 4.4 禁止使用power键的休眠功能
  8. android中在java代码中设置Button按钮的背景颜色
  9. Android获取手机号码和运营商信息的方法

随机推荐

  1. 在Android2.2模拟器上安装Android(安卓)M
  2. android的onCreateOptionsMenu()创建菜单
  3. android中的apk签名
  4. Android经典应用程序开发
  5. Android(安卓)OOM内存溢出解决方案之一
  6. Android(安卓)的开源电话/通讯/IM聊天项
  7. android service 学习
  8. 安卓 Android之开发简单小应用(一)
  9. Android开发周刊 第四期
  10. 用kotlin打印出漂亮的android日志(三)—