編輯:關於Android編程
事件響應對於android這種“頁程序”而言相當重要,因為這是與界面編程緊緊相關的知識;就如同Activity提供UI,而事件響應就提供具體的界面操作。
既然理解了其重要性,那麼我們就具體來了解下Android的事件響應處理吧。Android的事件響應處理其實相對來說比較簡單。參考《瘋狂Android講義》這本書中對Android事件響應的理解,其響應方式一共分為兩種:
1、基於監聽的事件響應模型
2、基於回調的事件響應模型
這兩者其實本質上也是無差別的,只是說具體的監聽器不同:一個則是綁定指定監聽器,並實現其監聽函數;一個是重寫了View中已經定義過的監聽函數。
那麼下面我們就來詳細的講解著兩種事件響應。
對於Android基於監聽的事件處理而言,主要就是android的界面組件綁定特定的事件監聽器,然後在監聽器中實現具體的代碼。
在事件監聽的處理模型中,主要涉及的是三類對象。(現在扯著三類對象大家可能覺得弄復雜了;但是請慢慢看,這樣說,易於後面更深刻的理解)
*Even Source (事件源)…………就是組件
*Even (事件)…………用戶操作
*Even Listener (事件監聽器)…………事件監聽器
當用戶按下一個按鈕或者單擊一個菜單項的時候,這個動作會激發一個相應的事件,而這個事件的事件源就是該按鈕或者菜單項。而按下之後產生的相應的變化,如刷新了界面,彈出下拉框或者彈出個Dialog等都是你事件監聽器在發揮作用。
以上的解釋相信大家就已經相當了解所謂的事件響應的一系列概念了。那麼現在就將這三類對象用具體的圖來表現出來。
從這張圖我們了解,外部操作產生事件源,事件源產生事件,而事件作為參數傳遞給了事件處理器也就是事件監聽器。然後在監聽器中就實現響應的處理方法,一陣套流程就走完了。
了解完事件監聽的模型,我們能知道,不同的組件(事件源)產生的事件,是需要不同的事件監聽器來實現的。這裡事件源(組件)是固定的(至少其父類是固定的,就那麼幾個:Button,ImageView,TextView啊等……),有固定的組件產生的事件那肯定也是固定的,那麼也因此事件監聽器也就是固定的。不同的在於實現事件監聽器的具體函數可能不同,這就是監聽的關鍵。
那麼針對剛剛說明的情況,不同的事件源,產生不同的事件,需要不同的事件監聽器來監聽,那麼以View為例,有哪些具體的事件監聽器呢?
*View.OnVClickListener…………單擊事件的事件監聽器
*View.OnCreateContextMenuListener…………創建上下文菜單的事件監聽器
*View.OnFocusChangeListener…………焦點改變的事件監聽器
*View.OnKeyListener…………按鍵的事件監聽器
*View.OnLongClickListener…………長單擊的事件監聽器
*View.OnTouchListener…………觸摸屏的事件監聽器
以上以View為例,介紹了其不同的幾個事件監聽器;其實本質上事件監聽器就是實現了特定接口的Java類的實例,這樣理解更深刻一些。現在我們再了解一下事件監聽器的幾種形式:
1、內部類形式
2、外部類形式
3、Activity本身作為事件監聽器類
4、匿名內部類
5、直接綁定到標簽
具體介紹著幾種形式吧。
內部類形式的監聽器可以被多次復用,相對來說編程界面夠簡潔,易理解。
MyListenermyListener = MyListener(); MyButton.setOnClickListener(myListener); MyTextView.setOnClickListener(myListener); …… Class MyListener extends View.onClickListener { onClick(View v) { Switch(V.getid()) Case MyButton: …… Case MyTextView: …… } }也正是因為這樣的原因,所以內部類形式的監聽器使用范圍比較廣泛;大量的內部類被用於android的源碼中。
外部類形式的監聽器比較少見。“瘋狂android講義”上如此分析原因:
1、 事件監聽器通常是屬於特定的gui界面,而定義成外部類的形式是不利於提高程序間的耦合性的。
2、 外部類其實就是因語言規定方面的原因,訪問gui界面的組件並不方便,需要傳入具體的控制的ui控件以方便使用,編程不簡潔。
這其中又提出,如果一個事件監聽器被多個gui界面所共享,而且完成的任務更強調業務邏輯(也就是說與特定的界面組件關系不大,這種情況不強調具體頁面),那麼可以考慮使用外部類。
Public class ActivityListener extends Activity implements OnClickListener { …… @ Override Public void onClick(View v) { 具體實現 } …… }參照“瘋狂android講義”將這個作為一種監聽器方式,其實這並沒有什麼值得一說的,因為它是在沒有什麼特色,而且這樣寫個人認為將使得程序復雜且不易讀。
其實匿名內部類的形式使用是比較舒適的,這主要是對比內部類,對比內部類中最有價值的“復用”功能。如果監聽器不強調“復用”這個時候匿名內部類是很好的選擇。實際上android工程中匿名內部類是使用最廣泛的一種監聽器形式了。
MyButton.setOnClickListener(newView.OnCickListener { onClick(View v) { 實現具體的監聽響應事件 …… } });
直接綁定到標簽這種監聽器的形式確實非常簡潔,直接聯系了xml語句和java語句;但是個人認為這樣做使得源碼不易讀,增添了麻煩,而且過多的聯系xml與java,這並不是一個明智的做法。
在上面的xml文件中綁定onclick屬性並直接命名“clickBandler”,這個命名很重要,將直接在java源碼中實現這個命名的點擊方法,然後就可以響應這個Button了。
Public class BindingTag extends Activity { @Override Publicvoid onCreate (Bundle savedInstanceState) { Super.onCreate(savedInstanceState); setContentView(R.layout.main); } //這就是響應clickBandler標簽的函數 publicvoid clickBandler(View source) { //響應的具體操作 ……… } }簡單的說完以上的5中監聽方式我們可以知道,其實重點還是內部類和匿名內部類,這才是監聽的關鍵;而其余的只需要做了解就可以了。
回調的事件處理時比較簡單的,易於理解;對比監聽的事件處理,回調其實就是相當於是將事件源與事件監聽器放在了同一個控件中了,這樣做個人理解是為了更方便的實現面向對象,規定特定的組件響應特定的操作,將屬性歸類。
為了實現回調機制的事件處理,android為所有的gui組件都提供了回調方法,這裡以View為例來說明:
(View該類的毀掉監聽方法)
*boolean onKeyDown(int keyCode , KeyEventevent).用戶在該組件上按下時觸發的
*boolean onKeyLongPress(int keyCode ,keyEvent event).用戶在該組件上長按時候觸發的
*boolean onkeyShorcut(int keyCode ,keyEvent event);當一個鍵盤快捷鍵時觸發該事件
*boolean onkeyUp(int keyCode , keyEventevent)用戶松開該按鍵的時候觸發的事件
*boolean onTouchEvent(MotionEvent event).用戶在該組件上觸發觸摸屏時候觸發該方法
*boolean onTrackballEvent(MotionEventevent).用戶在該組件商觸發軌跡球的時候觸發該方法
其實解釋ui控件的回調函數的事件處理機制主要是為了自定義View控件來鋪路的,而自定義控件的響應事件具體就要介紹回調事件傳播了,因此我們可以通過回調事件的傳播來看自定義View的回調機制。
回調事件傳播:具體就是指所有基於回調事件處理方法都有一個boolean類型的返回值,而這個返回值就是代表這個回調函數是否已經完全處理了該事件。
*如果返回為true,則表示已經完全處理了該事件,該事件不會再傳播出去;
*如果為false,則表示事件還會再逐層的傳播出去
這僅是說是基於回調的事件傳播,監聽的話貌似沒有這方面的考慮。原因在於回調的話由於繼承(個人是這樣理解的),回調函數會逐層逐層的反饋事件是否已經處理掉了,而判斷的依據就是return true or? False!!
這樣一層一層的回調反饋。
看看這個示例表達的就是這個意思
public class Propagation extends Activity { @Override public void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Buttonbn = (Button) findViewById(R.id.bn); // 為bn綁定事件監聽器 bn.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View source ,intkeyCode, KeyEvent event) { // 只處理按下鍵的事件 if (event.getAction() ==KeyEvent.ACTION_DOWN) { Log.v("-Listener-","the onKeyDown in Listener"); } // 返回false,表明該事件會向外傳播 return true; // ① } }); } // 重寫onKeyDown方法,該方法可監聽它所包含的所有組件的按鍵被按下事件 @Override public boolean onKeyDown(int keyCode, KeyEventevent) { super.onKeyDown(keyCode ,event); Log.v("-Activity-", "the onKeyDown in Activity"); //返回false,表明並未完全處理該事件,該事件依然向外擴散 return false; }
其實我們仔細對比這兩種事件處理模型就能看出來,基於監聽的事件處理模型是有極大的優勢的,主要是邏輯清晰,代碼易讀,容易維護;而且android的事件處理機制還導致基於監聽的事件監聽器會被優先觸發。通過對比我們就基本完全理解了android的事件監聽模型了!
本文所需要實現的就是這樣一種有逼格的效果:右上角加了個圖片框,按下確定可以裁剪正方形區域裡的圖片並顯示在右上角。實現思路:1:首先需要自定義一個ZoomImageView
Bluetooth Using the Bluetooth APIs, an Android application can perform the following:
這是在網上找的,不過忘了在哪裡找的,經過很多比較測試,發現這個方法不會 oom,目前來看 我一直沒有遇過,今天才找到這個以前建立的工程,記錄下來:先給大家展示下效果圖:p
本節引言: 本節我們介紹的是Vibrator(振動器),是手機自帶的振動器,別去百度直接搜針振動器,因為 你的搜索結果可能是如圖所示的神秘的道具,或者其他神秘