标签:
底层的怎么调用我说不清楚, 我们来关注下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>
标签:
原文地址:http://my.oschina.net/janson2013/blog/412778