假設說事件監聽機制是一種托付式的事件處理,那么回調機制則與之相反,對於基於回調的事件處理模型來說,事件源和事件監聽器是統一的,或者說事件監聽器全然消失了,當用戶在GUI控件上激發某個事件時,控件自己特定的方法將會負責處理該事件。
轉載請表明出處:http://blog.csdn.net/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.源代碼實戰
實現:自己定義一個button。重寫其觸摸的回調方法。
(1)MyButton.java:自己定義組件
package com.example.android_event2; import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.widget.Button; import android.widget.Toast; public class MyButton extends Button { //構造方法 public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } //回調方法 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); Toast.makeText(getContext(),"您按下了數字:"+keyCode,Toast.LENGTH_SHORT).show(); return true; //返回true,表明該事件不會向外擴散 } }
(2)layouyt/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <!--方法一:在XML布局文件里創建組件--> <com.example.android_event2.MyButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="回調測試" /> </LinearLayout> (3)MainActivity.java:主Activity package com.example.android_event2; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //方法二:Java代碼中配置自己定義組件 } }
效果演示:


源代碼分析:在布局文件里配置自己定義的組件---->
<完整的包名.類名 須要設置的相關屬性/>
三、事件處理的傳播
1. 基於回調方法事件處理的傳播
差點兒全部基於回調的事件處理方法都有一個boolean類型的返回值,該返回值用於標識該處理方法能否全然處理該事件。 假設處理事件的回調方法返回true,表明該處理方法已全然處理該事件,該事件不會傳播出去; 假設處理事件的回調方法返回false。表明該處理方法並未全然處理該事件,該事件將會繼續向外傳播。
對於基於回調事件傳播而言,某組件上所發生的事情不僅激發該組件上的回調方法。也會觸發該組件所在Activity的回調方法(前提是事件能傳播到Activity)。
2.源代碼實戰
實現:自己定義一個button,重寫其觸摸的回調方法、為其注冊觸摸事件監聽器並重寫它所在Activity上的觸摸回調方法,觀察事件處理順序。
(1)MainActivity.java
package com.example.android_event2; import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnKeyListener; import android.widget.Button; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //採用監聽模式 Button myButton = (Button)findViewById(R.id.btn); myButton.setOnKeyListener(new OnKeyListener(){ public boolean onKey(View v, int keyCode, KeyEvent event) { System.out.println("組件所綁定的事件監聽器被觸發"); return false; } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); System.out.println("該組件所在的Activity的回調方法onKeyDown被調用"); return false; //返回true,表明該事件不會向外擴散 } }
(2)MyButton.java
package com.example.android_event2; import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.widget.Button; public class MyButton extends Button { //構造方法 public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } //回調方法 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); System.out.println("自己定義組件中的回調方法onKeyDown被調用"); return false; //返回true,表明該事件不會向外擴散 } }
(3)layout/main.xml
package com.example.android_event2; import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.widget.Button; public class MyButton extends Button { //構造方法 public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } //回調方法 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); System.out.println("自己定義組件中的回調方法onKeyDown被調用"); return false; //返回true,表明該事件不會向外擴散 } }
效果演示:


源代碼分析:
通過實驗結果可知。當任意按下一個鍵后。 最先觸發的是該組件所綁定的事件監聽器,接着才觸發該組件提供的事件回調方法。最后才傳播到該組件所在的Activity。假設我們讓不論什么一個事件處理方法返回了true。那么該事件將不會繼續向外傳播。
四、直接綁定到標簽
Android提供了一種直接在界面布局文件里為指定標簽綁定事件處理方法的機制。對於非常多Android界面控件而言,它們都支持如onClick、onLongClick等屬性,這些屬性的屬性值是一個形如xxx(View source)方法的方法名。
比如,在布局文件里為button加入單擊事件的處理方法例如以下:
<Button
android:layout_width=”wrap_content”
android:layout_heigth=”wrap_content”
android:text=”單擊我”
android:onClick=”clickHandler”/>
1.源代碼實戰
(1)MainActivity.java
package com.example.android_event3; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class MainActivity extends Activity { private EditText text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (EditText)findViewById(R.id.result); } //將clickHandler方法直接綁定到標簽 public void clickHandler(View source) { text.setText("中華人民共和國萬歲。"); } }
(2)layout/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="單擊我" android:onClick="clickHandler"/> <EditText android:id="@+id/result" android:inputType="none" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
效果演示:

