Activity的按钮消息传递


     底层的怎么调用我说不清楚, 我们来关注下activity的按钮消息传递.

      acitivty中有三个关于按键消息处理的方法.  dispatchKeyEvent 和onKeyDown ,onKeyUp . 由于Activity是View的子类, 所以这三个方法都是重写View的三个方法.

引用<android内核解析>中的一句话: 

     当按键消息进入activity的内部后, Acitivty内部的dispatchKeyEvent有默认的逻辑处理. 它先回调该Activity保函的window对象的相应方法, 并将消息派发DecorView对象的视图内部. 然后才回调Acitivty内部的onKeyDown()和onKeyUp()函数. .......  假如应用程序重载dispatchKeyEvent(),从而不按照默认的逻辑进行处理,这有可能导致按键消息永远不会传递到View数内部的视图中,所以一般情况下并不重载该函数

  1.    上面说了当按键消息进入activity的内部中.  并不是说所有的按键的消息都能进入activity中 . 举列 home键就不能 . 这是由底层所分发的.

  2.  上面所说假如重载dispatchKeyEvent() ,在dispatchKeyEvent 里对一些按键没有调用super.dispatchKeyEvent , onKeyDown , onKeyUp是不会被调用 . 为什么 ? 因为经过Acitivty dispatchKeyEvent才进行对按键的分发 , 其中会分发到onKeyDown ,onKeyUp . 

  3. 在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>


你可能感兴趣的:(Activity的按钮消息传递)