底层的怎么调用我说不清楚, 我们来关注下activity的按钮消息传递.
acitivty中有三个关于按键消息处理的方法. dispatchKeyEvent 和onKeyDown ,onKeyUp . 由于Activity是View的子类, 所以这三个方法都是重写View的三个方法.
引用<android内核解析>中的一句话:
当按键消息进入activity的内部后, Acitivty内部的dispatchKeyEvent有默认的逻辑处理. 它先回调该Activity保函的window对象的相应方法, 并将消息派发DecorView对象的视图内部. 然后才回调Acitivty内部的onKeyDown()和onKeyUp()函数. ....... 假如应用程序重载dispatchKeyEvent(),从而不按照默认的逻辑进行处理,这有可能导致按键消息永远不会传递到View数内部的视图中,所以一般情况下并不重载该函数
上面说了当按键消息进入activity的内部中. 并不是说所有的按键的消息都能进入activity中 . 举列 home键就不能 . 这是由底层所分发的.
上面所说假如重载dispatchKeyEvent() ,在dispatchKeyEvent 里对一些按键没有调用super.dispatchKeyEvent , onKeyDown , onKeyUp是不会被调用 . 为什么 ? 因为经过Acitivty dispatchKeyEvent才进行对按键的分发 , 其中会分发到onKeyDown ,onKeyUp .
在Acivity调用了super.dispatchKeyEvent , 在View里面就会得到由Activity派遣的按键消息吗 ? 答案是否 . 在源码中 先经过Acitivty的Window內进行消息过滤 , 过滤好的消息再分发给View . 例如返回键 View就获取不了
/** * Called to process key events. You can override this to intercept all * key events before they are dispatched to the window. Be sure to call * this implementation for key events that should be handled normally. * * @param event The key event. * * @return boolean Return true if this event was consumed. */ public boolean dispatchKeyEvent(KeyEvent event) { onUserInteraction(); Window win = getWindow(); if (win.superDispatchKeyEvent(event)) { return true; } View decor = mDecor; if (decor == null) decor = win.getDecorView(); return event.dispatch(this, decor != null ? decor.getKeyDispatcherState() : null, this); }
下面是一些测试代码
MainAcitivty.java
package com.example.qiang.mykeyaction; import android.app.Activity; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { public static final String TAG ="MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button but = (Button) findViewById(R.id.but); but.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this , "asdfdsf" ,Toast.LENGTH_SHORT).show(); } }); MyView myView = (MyView) findViewById(R.id.myView); myView.setFocusable(true); } /*格外小知识 此方法是activity的方法,当此activity在栈顶时,用户对手机:触屏点击,按home,back,menu键都会触发此方法。 注:下拉statubar,旋转屏幕,锁屏,不会触发此方法.*/ @Override public void onUserInteraction() { super.onUserInteraction(); // Log.d(TAG ,"onUserInteraction"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.d(TAG ," onKeyDown keyCode = "+keyCode ); return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { Log.d(TAG ,"onKeyUp keyCode = "+keyCode ); return super.onKeyUp(keyCode, event); } //只是监听按钮信息 不包括触摸信息 @Override public boolean dispatchKeyEvent(KeyEvent event) { //当 不调用父类的dispatchKeyEvent 是不会返回到 onKeyDown ,onKeyUp 的 // return false; // return true; return super.dispatchKeyEvent(event); } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add("菜单"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } }
package com.example.qiang.mykeyaction; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; /** 用于研究MotionEven * Created by qiang on 15/5/9. */ public class MyView extends View { public static final String TAG ="MyView"; public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.d(TAG, "onKeyDown keyCode = " + keyCode); return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { Log.d(TAG, "onKeyUp keyCode = " + keyCode); return super.onKeyUp(keyCode, event); } }
layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@+id/but" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="123" /> <com.example.qiang.mykeyaction.MyView android:id="@+id/myView" android:layout_width="100dp" android:layout_height="100dp" android:background="@android:color/background_dark" /> </LinearLayout> </RelativeLayout>