Android笔记二十四.Android基于回调的事件处理机制

本文深入讲解了Android中基于回调机制的事件处理模型,包括自定义控件实现、事件处理传播及直接绑定到标签的方法。
如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器完全消失了,当用户在GUI控件上激发某个事件时,控件自己特定的方法将会负责处理该事件
转载请表明出处:http://blog.youkuaiyun.com/u012637501(嵌入式_小J的天空)
一、View类的常见回调方法
    为了使用回调机制来处理GUI控件上所发生的事件,需要为该组件提供对应的事件处理方法,而Java又是一种静态语言,我们无法为每个对象动态地添加方法,因此只能通过继承GUI控件类,并重写该类的事件处理方法来实现。 Android平台中,每个View都有自己处理特定事件的回调方法,我们可以通过重写View中的这些回调方法来实现相应的事件。

二、基于回调的事件处理开发方法
1.自定义控件的一般步骤
(1)定义自己组件的类名,并让该类继承View类或一个现有的View的子类;
(2)重写父类的一些方法,通常需要提供一个构造器,构造器是创建自定义控件的基本方式。当Java代码创建该控件或根据XML布局文件加载并构建界面时都将调用该构造器,根据业务需要重写父类的部分方法。例如onDraw方法,用于实现界面显示,其他方法还有onSizeChanged()、onKeyDown()、onKeyUp()等。
(3)使用自定义的组件,既可通过Java代码来创建,也可以通过XML布局文件进行创建,需要注意的是在XML布局文件中,该组件的标签是完整的包名+类名,而不再仅仅是原来的类名。
2.源码实战
实现:自定义一个按钮,重写其触摸的回调方法。
(1)MyButton.java:自定义组件
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.android_event2;  
  2. import android.content.Context;  
  3. import android.util.AttributeSet;  
  4. import android.view.KeyEvent;  
  5. import android.widget.Button;  
  6. import android.widget.Toast;  
  7. public class MyButton extends Button  
  8. {  
  9.  //构造方法  
  10.  public MyButton(Context context, AttributeSet attrs) {  
  11.   super(context, attrs);  
  12.  }  
  13.  //回调方法  
  14.  @Override  
  15.  public boolean onKeyDown(int keyCode, KeyEvent event) {  
  16.    super.onKeyDown(keyCode, event);  
  17.    Toast.makeText(getContext(),"您按下了数字:"+keyCode,Toast.LENGTH_SHORT).show();  
  18.    return true//返回true,表明该事件不会向外扩散  
  19.  }  
  20. }  
(2)layouyt/main.xml
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:orientation="vertical"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.    <!--方法一:在XML布局文件中创建组件-->  
  6.     <com.example.android_event2.MyButton  
  7.         android:layout_width="wrap_content"  
  8.         android:layout_height="wrap_content"  
  9.         android:layout_gravity="center_horizontal"  
  10.         android:text="回调测试" />  
  11. </LinearLayout>  
  12. (3)MainActivity.java:主Activity  
  13. package com.example.android_event2;  
  14. import android.app.Activity;  
  15. import android.os.Bundle;  
  16. public class MainActivity extends Activity {  
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.         //方法二:Java代码中配置自定义组件  
  22.     }  
  23. }  
效果演示:

源码分析:在布局文件中配置自定义的组件---->
                                                                    <完整的包名.类名  需要设置的相关属性/>
三、事件处理的传播
1. 基于回调方法事件处理的传播
      几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件。 如果处理事件的回调方法返回true,表明该处理方法已完全处理该事件,该事件不会传播出去; 如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件将会继续向外传播。   
     对于基于回调事件传播而言,某组件上所发生的事情不仅激发该组件上的回调方法,也会触发该组件所在Activity的回调方法(前提是事件能传播到Activity)。
2.源码实战
实现:自定义一个按钮,重写其触摸的回调方法、为其注册触摸事件监听器并重写它所在Activity上的触摸回调方法,观察事件处理顺序。
(1)MainActivity.java
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.android_event2;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.view.KeyEvent;  
  5. import android.view.View;  
  6. import android.view.View.OnKeyListener;  
  7. import android.widget.Button;  
  8. public class MainActivity extends Activity {  
  9.     @Override  
  10.     protected void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.main);  
  13.         //采用监听模式  
  14.         Button myButton = (Button)findViewById(R.id.btn);  
  15.         myButton.setOnKeyListener(new OnKeyListener(){  
  16.    public boolean onKey(View v, int keyCode, KeyEvent event) {  
  17.     System.out.println("组件所绑定的事件监听器被触发");  
  18.     return false;  
  19.    }  
  20.            
  21.         });  
  22.     }  
  23.     @Override  
  24.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  25.        super.onKeyDown(keyCode, event);  
  26.        System.out.println("该组件所在的Activity的回调方法onKeyDown被调用");  
  27.        return false;    //返回true,表明该事件不会向外扩散  
  28.     }  
  29. }  
(2)MyButton.java
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.android_event2;  
  2. import android.content.Context;  
  3. import android.util.AttributeSet;  
  4. import android.view.KeyEvent;  
  5. import android.widget.Button;  
  6. public class MyButton extends Button  
  7. {  
  8.  //构造方法  
  9.  public MyButton(Context context, AttributeSet attrs) {  
  10.   super(context, attrs);  
  11.  }  
  12.  //回调方法  
  13.  @Override  
  14.  public boolean onKeyDown(int keyCode, KeyEvent event) {  
  15.    super.onKeyDown(keyCode, event);  
  16.    System.out.println("自定义组件中的回调方法onKeyDown被调用");  
  17.    return false;    //返回true,表明该事件不会向外扩散  
  18.  }  
  19. }  
(3)layout/main.xml
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.android_event2;  
  2. import android.content.Context;  
  3. import android.util.AttributeSet;  
  4. import android.view.KeyEvent;  
  5. import android.widget.Button;  
  6. public class MyButton extends Button  
  7. {  
  8.  //构造方法  
  9.  public MyButton(Context context, AttributeSet attrs) {  
  10.   super(context, attrs);  
  11.  }  
  12.  //回调方法  
  13.  @Override  
  14.  public boolean onKeyDown(int keyCode, KeyEvent event) {  
  15.    super.onKeyDown(keyCode, event);  
  16.    System.out.println("自定义组件中的回调方法onKeyDown被调用");  
  17.    return false;    //返回true,表明该事件不会向外扩散  
  18.  }  
  19. }  

效果演示:

源码分析:
    通过实验结果可知,当随意按下一个键后。 最先触发的是该组件所绑定的事件监听器,接着才触发该组件提供的事件回调方法,最后才传播到该组件所在的Activity。如果我们让任何一个事件处理方法返回了true,那么该事件将不会继续向外传播。
四、直接绑定到标签
    Android提供了一种直接在界面布局文件中为指定标签绑定事件处理方法的机制。对于很多Android界面控件而言,它们都支持如onClick、onLongClick等属性,这些属性的属性值是一个形如xxx(View source)方法的方法名。
例如,在布局文件中为按钮添加单击事件的处理方法如下:
<Button
        android:layout_width=”wrap_content”
        android:layout_heigth=”wrap_content”
        android:text=”单击我”
        android:onClick=”clickHandler”/>
1.源码实战
(1)MainActivity.java
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.android_event3;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.view.View;  
  5. import android.widget.EditText;  
  6. public class MainActivity extends Activity {  
  7.  private EditText text;  
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main);  
  12.         text = (EditText)findViewById(R.id.result);  
  13.     }  
  14.     //将clickHandler方法直接绑定到标签  
  15.     public void clickHandler(View source)  
  16.     {  
  17.      text.setText("中华人民共和国万岁!");  
  18.     }  
  19. }  
(2)layout/main.xml
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.  android:orientation="vertical"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.  <Button  
  6.      android:layout_width="match_parent"  
  7.      android:layout_height="wrap_content"  
  8.      android:text="单击我"  
  9.      android:onClick="clickHandler"/>  
  10.  <EditText  
  11.      android:id="@+id/result"  
  12.      android:inputType="none"  
  13.      android:layout_width="match_parent"  
  14.      android:layout_height="wrap_content"/>  
  15. </LinearLayout>  
效果演示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值