基于回调的事件处理——基于回调的事件传播

      几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件:

  •  如果处理事件的回调方法返回true,表明该处理方法以完全处理该事件,该事件不会传播出去。
  •  如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件会传播出去。

      对于基于回调的事件传播而言,某组件上所发生的事件不仅激发该组件上的回调方法,也会触发该组件所在Activity的回调用法——只要事件能传播到该Activiy。

      下面的一个程序示范了Android系统中的事件传播,该程序重写了Button类的onKeyDown(int keyCode,KeyEvent event)方法,而且重写了该Button所在Activity的onKeyDown(int keyCode,KeyEvent event)方法——而且程序没有阻止事件传播,因此程序可以看到事件从Button传播到Activity的情形。

      下面是从Button派生而出的MyButton子类代码。

package com.example.studyevent;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MyButton extends Button {
   
    public MyButton(Context context,AttributeSet set) {
        
        super(context,set);
        
        // TODO Auto-generated constructor stub
    }
    @Override
     public boolean onKeyDown(int keyCode,KeyEvent event)
     {
        super.onKeyDown(keyCode, event);
        Log.v("-crazyit.org-","the onKeyDown is MyButton");
        //返回false,表明并未完全处理该事件,该事件依然向外扩散
        return false;
     }
    @Override
     public boolean onTouchEvent(MotionEvent event)
     {
        
        Toast.makeText(this.getContext(),"触发事件onTouchEvent", Toast.LENGTH_SHORT).show();
        return false;
         
         
     }
}

    上面的MyButton子类重写了onKeyDown(int keyCode,KeyEvent event)方法,当用户在该按钮上按下某个键时将会触发该方法。但由于该方法返回了false,这就意味着该事件还会继续向外传播。
    该程序也按前一个示例的方式使用该自定义组件,并在Activity中重写public boolean onKeyDown(int keyCode,KeyEvent event)方法,该方法也会在某个按键被按下时被回调。

     看如下Activity类代码。

package com.example.studyevent;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.Button;

public class Propagation extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_propagation);
        Button bn=(Button)findViewById(R.id.bn);
        //为bn按钮绑定监听器
        bn.setOnKeyListener(new OnKeyListener(){

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // TODO Auto-generated method stub
                //只处理按下键的事件
                if(event.getAction()==KeyEvent.ACTION_DOWN)
                {
                    Log.v("-Listener", "the onKeyDown in Listener");
                }
                //返回false,表明该事件会向外传播
                return false; //①
            }});
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.propagation, menu);
        return true;
    }
    //重写onKeyDown方法,该方法可监听它所包含的所有组件的按键被按下事件
    @Override
    public boolean onKeyDown(int keyCode,KeyEvent event)
    {
        super.onKeyDown(keyCode, event);
        Log.v("-Activity-","the onKeyDown is Activity");
        //返回false,表明并未完全处理该事件,该事件依然向外扩展
        return false;
    }

}

       从上面的程序可以看出,粗体字代码重写了Activity的onKeyDown(int keyCode,KeyEvent event)方法,当该Activity包含的所有组件上按下某个键时,该方法都可能被触发——只要该组件没有完全处理该事件。
       不仅如此,上面的程序还采用监听模式来处理该按钮上的按键被按下的事件。

       运行上面的程序,先把焦点移动到程序界面的按钮上,然后按下模拟器右边的按键,将可以在DDMS的LogCat中看到如图所示的输出:

 

 

 

     从上图我们可以看出,当该组件上发生某个按键被按下的事件时,Android系统最先触发的应该是该按键上绑定的事件监听器,接着才触发该组件提供的事件回调方法,然后还会传播到该组件所在的Activity——但如果我们让任何一个事件处理方法返回了true,那么该事件将不会继续向外传播。例如我们改写上面的Activity代码,将程序中①号代码改为return true,然后再运行该程序、把焦点定位到该按钮上之后单击某个按键,在DDMS的LogCat中将看到下图所示的输出。

     

    

      

posted @ 2013-11-05 12:06  TealerProg  Views(1023)  Comments(0Edit  收藏  举报