Android有兩種方式的事件處理:
1、基於回調的事件處理 2、基於監聽器的事件處理
一、先來大概說明一下監聽器的事件處理的實現原理
(學過AWT 、Swing的同學對監聽器基本有一點了解。)
===》》》 監聽事件是一種“面向對象”的事件處理 《《《===
涉及三類對象:
- Event Source(事件源): 也就是按鈕,菜單,窗口等
- Event(事件):就是操作的狀態,單擊、觸摸、長按、雙擊等
- Event Listener(事件監聽器):對用戶的操作做出響應,也就是單擊按鈕了使他有反應
既然他們都是獨自的對象,處理方式也就比較寬泛。一個監聽器中可以有多個事件被監聽
public class MainActivity extends Activity { private Button button1, button2, button3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button1 = (Button) findViewById(R.id.button1); button2 = (Button) findViewById(R.id.button2); button3 = (Button) findViewById(R.id.button3); button1.setOnClickListener(listener); button2.setOnClickListener(listener); button3.setOnClickListener(listener); } private OnClickListener listener = new OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.button1: Toast.makeText(MainActivity.this,"點擊了button1", 1).show(); break; case R.id.button2: Toast.makeText(MainActivity.this,"點擊了button2", 1).show(); break; case R.id.button3: Toast.makeText(MainActivity.this,"點擊了button3", 1).show(); break; } } }; }
通過view.getId()來獲取不同的組件,switch來判斷不同組件的事件
當然,一個事件源也可以有多個不同的監聽器監聽不同的事件,菜單可以有單擊事件,也可以有長按事件。
有個有意思的比喻:說android的事件處理機制是一種委派式事件處理方式,普通UI組件將發生的事件交給監聽器去處理,自己不處理。好比如:發生火災了,交給消防局處理,發生打架了交給公安局處理,並且消防局和公安局又可以同時處理多個火災和打架事件。 這樣的委派式處理方式提高了程序的可維護性。挺好。
====》》》 實現監聽器的5種形式 《《《===
1、內部類形式,此時監聽器可以被復用,監聽器還可以自由訪問外部類中所有界面組件
2、外部類形式(這種方式少見),首先不利於提高程序內聚性,而且監聽器也不能自由訪問界面中組件。當然也有用到的時候,比如某個監聽器需要被多個GUI界面所共享的時候。
3、Activity本身作為監聽器(更少見),implements OnClickListener (特例)就可以實現
4、匿名內部類(使用廣泛),
button.setOnClickListener(new OnClickListener(){
@override
Public void onClick(View v){
}
}
);
注意: new的監聽器可以放在方法的括號中,當多個按鈕需要實現這種監聽時可以拿出來,制定給某個變量,(上面介紹的一個監聽器中可以有多個事件被監聽的代碼就是這樣)
5、還可以直接綁定到標簽
比如Button的一個屬性 android:onClick=“clickHandler”
接下來實現一個clickHandler方法就可以了、注意要傳一個View參數,不然沒有反應 View形參代表被單擊的UI組件。
Public void clickHandler( View source) { }
二、 下面說一下基於回調的事件處理
1、上面的監聽機制是一種委托式處理,那么回調機制則相反,回調機制則是發生某個事件時UI組件自己處理事件。
(貌似基於回調的事件處理是用在自定義的UI組件中)
自定義某個組件然后繼承該GUI組件類,並重寫該類事件處理方法
以View為例、先說一下常見的方法:
- boolean onKeyDown(int keyCode, KeyEvent event) 按下
- boolean onKeyLongPress(int keyCode, KeyEvent event) 長按
- boolean onKeyShortcut(int keyCode, KeyEvent event) 鍵盤快捷鍵事件觸發
- boolean onKeyUp(int keyCode ,KeyEvent event) 松開某個鍵
- boolean onTouchEvent(MotionEvent event) 觸屏事件
- boolean onTrackballEvent(MotionEvent event) 軌跡球屏事件
在界面布局中使用自定義View時,要用全限定類名(包名.類名),
有個簡單方法:將鼠標光標放在自定義類上面,將出現的框中內容直接復制就行
2、基於回調事件的傳播
所有基於回調的事件處理方法都有一個boolean類型的返回值,該返回值用於標識該處理方法能否完全處理該事件
True : 表示該處理方法已完全處理該事件,事件不會傳播出去
False: 沒有完全處理該事件,事件會傳播出去
既然要傳播,都傳向哪里呢,下面介紹
有3個地方需要返回boolean類型,也就是事件是否完全處理
(1) 自定義組件重寫的回調方法return一個
1 import android.content.Context; 2 import android.util.AttributeSet; 3 import android.util.Log; 4 import android.view.KeyEvent; 5 import android.widget.Button; 6 7 public class MyButton extends Button 8 { 9 public MyButton(Context context , AttributeSet set) 10 { 11 super(context , set); 12 } 13 @Override 14 public boolean onKeyDown(int keyCode, KeyEvent event) 15 { 16 super.onKeyDown(keyCode , event); 17 Log.v("--MyButton--" , "the onKeyDown in MyButton"); 18 // 返回false,表明並未完全處理該事件,該事件依然向外擴散 19 return false; 20 } 21 }
(2) 綁定監聽機制實現的事件處理方法中 return 一個
1 @Override 2 public void onCreate(Bundle savedInstanceState) 3 { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.main); 6 Button bn = (Button) findViewById(R.id.bn); 7 // 為bn綁定事件監聽器 8 bn.setOnKeyListener(new OnKeyListener() 9 { 10 @Override 11 public boolean onKey(View source 12 , int keyCode, KeyEvent event) 13 { 14 // 只處理按下鍵的事件 15 if (event.getAction() == KeyEvent.ACTION_DOWN) 16 { 17 Log.v("-Listener-", "the onKeyDown in Listener"); 18 } 19 // 返回false,表明該事件會向外傳播 20 return true; // ① 21 } 22 }); 23 }
(3) Activity中重寫回調方法,return一個
1 // 重寫onKeyDown方法,該方法可監聽它所包含的所有組件的按鍵被按下事件 2 @Override 3 public boolean onKeyDown(int keyCode, KeyEvent event) 4 { 5 super.onKeyDown(keyCode , event); 6 Log.v("-Activity-" , "the onKeyDown in Activity"); 7 //返回false,表明並未完全處理該事件,該事件依然向外擴散 8 return false; 9 }
下面說一下傳播的順序:
傳播順序是:首先傳播到組件綁定的監聽器上,然后是自定義組件重寫的事件方法,最后傳播到組件所在Activity,當然,如果任何一個返回了true,那么事件將不會繼續向外傳播。
