在Android平台上,捕獲使用者在介面上的觸發事件有很多種方法,View類就提供這些方法。你在使用各種View視圖來布局介面時,會發現幾個公用的回調方法來捕捉有用的UI觸發事件,當事件在某個View對象上被觸發時,這些方法會被系統架構通過這個對象所調用,例如:當一個View(如一個Button)被點擊,onTouchEvent()方法會在該對象上被調用,所以,為了捕獲和處理事件,必須去繼承某個類,並重載這些方法,以便自己定義具體的處理邏輯,顯然,你更容易明白,為什麼在你使用View類時會嵌套帶有這些回調方法的介面類,這些介面稱為event listeners,它是你去擷取UI互動事件的工具在你繼承View類,以便建立一個自訂群組,也許你想繼承Button , 你會更普遍使用事件監聽來捕捉使用者的互動,在種情況下,你可以使用類的event handlers.來預定義事件的處理方法。
Event Listeners
View類裡的event listener是一個帶有回調方法的介面,當UI裡的組建是被使用者觸發時,這些方法會被系統架構所調用
onClick()
來自View.OnClickListener 它會被調用當點擊這個Item(在觸摸模式),或者當游標聚集在這個Item上時按下“確認”鍵 ,導航鍵,或者軌跡球。
onLongClick()
來自View.OnLongClickListener. 它會被調用當長按這個Item(在觸摸模式),或者當游標聚集在這個Item上時間長度按 “確認”鍵 ,導航鍵,或者軌跡球。
onFocusChange()
來自View.OnFocusChangeListener 它會被調用當游標移到或離開這個Item,
onKey()
來自View.OnKeyListener..它會被調用,當游標移到這個Item,按下和釋放一個按鍵的時候
onTouch()
來自View.OnTouchListener. 它會被調用 ,在這個Item的範圍內點觸的時候
onCreateContextMenu()
來自View.OnCreateContextMenuListener. 它會被調用, 當操作功能表被建立時(由於持續的“長按”) 見討論Creating Menus更多的資訊。
這些方法和嵌套介面類都是一一對應的,如果確定其中一種方法處理你的互動事件,你需要在Activity中實現這個帶有這個方法的介面,並把它作為匿名類,然後,通過執行個體的View.set...Listener() 方法來設定監聽器(例如,調用setOnClickListener(),來設定OnClickListener做為監聽器)
下面是為一個按鈕設定監聽器的例子:
// Create an anonymous implementation of OnClickListener private OnClickListener mCorkyListener = new OnClickListener() { public void onClick(View v) { // do something when the button is clicked } }; protected void onCreate(Bundle savedValues) { ... // Capture our button from layout Button button = (Button)findViewById(R.id.corky); // Register the onClick listener with the implementation above button.setOnClickListener(mCorkyListener); ... }
}
下面這個列子我們會發現用Activity去實現OnClickListener介面,並作為它的一部分,會更方便,而不必去載入額外的類和對象
public class ExampleActivity extends Activity implements OnClickListener { protected void onCreate(Bundle savedValues) { ... Button button = (Button)findViewById(R.id.corky); button.setOnClickListener(this); } // Implement the OnClickListener callback public void onClick(View v) { // do something when the button is clicked } ... }
這裡注意一下,以上的例子可以看出onClick()是沒有傳回值的,但是有些事件處理方法是必須帶傳回值,它取決於的具體的事件,有些那麼做的原因,看下面的例子:
onLongClick()
它返回的布爾值表明你已經完成了這個事件的處理,還是應該把它繼續傳下去。返回true表明已經處理完成並且停止了傳遞,如果返回為false表明事件還沒有完成,或者它還需要繼續被傳遞給其他的監聽器
onKey()
它返回的布爾值表明你已經完成了這個事件的處理,還是應該把它繼續傳下去。返回true表明已經處理完成並且停止了傳遞,如果返回為false表明事件還沒有完成,或者它還需要繼續被傳遞給其他的監聽器
onTouch()
它返回的布爾值表明你是否已經完成了這次事件的行動,重要的是後面可能還有很多後續的行動,這樣,如果你返回false,表明在接到下一次的後續行動中,你還沒有完成之前行為也沒有意向去處理隨後的行動,因此,在這個事件的後續行動中將不會再被調用。 如fingure手勢,或最終行動事件
記住:我們所關注的事件肯定是發生在高亮聚集的焦點,它從總視圖(頂級的)被一級一級的向下傳遞,直到我們想要關注的組件,當焦點聚集在這個視圖(或視圖中的子視圖)時 ,你能夠使用dispatchKeyEvent() 作為一種代替方法,來捕獲在視圖上的按鍵事件,你還可以使用onKeyDown()和onKeyUp().來捕獲所有事件內的互動活動
注意:在 Android 架構中會調用event handlers先處理事件,然後會適當的傳遞給二級預設的預定義handlers中;因此 如果返回true,將會停止這個事件的傳遞,View中預設事件處理方法的回調也會被阻止。因此,當你返回true肯定表明你是要終止這個事件的延續。(這個地方有點不懂。。。原文是:Android will call event handlers first and then the appropriate default handlers from the class definition second. As such, returning true from these event listeners will stop the propagation of the event to other event listeners and will also block the callback to the default event handler in the View. So be certain that you want to terminate the event when you return true.)
Event Handlers
如果您建立一個繼承於View自訂群組件,然後您可以定義一些回調方法用作預設的事件處理常式。該檔案中關於Building Custom Components,您會學習一些共用的回調方法用於事件處理,其中包括:
onKeyDown(int, KeyEvent)
- Called when a new key event occurs.
onKeyUp(int, KeyEvent)
- Called when a key up event occurs.
onTrackballEvent(MotionEvent)
- Called when a trackball motion event occurs.
onTouchEvent(MotionEvent)
- Called when a touch screen motion event occurs.
onFocusChanged(boolean, int, Rect)
- Called when the view gains or loses focus.還有其他一些方法,這不屬於View類,但可以直接影響到你處理事件的方式,所以在布局內管理更複雜的事件可以考慮到這些方法:
Activity.dispatchTouchEvent(MotionEvent)
- This allows your Activity
to intercept all touch events before they are dispatched to the window.
ViewGroup.onInterceptTouchEvent(MotionEvent)
- This allows a ViewGroup
to watch events as they are dispatched to child Views.
ViewParent.requestDisallowInterceptTouchEvent(boolean)
- Call this upon a parent View to indicate that it should not intercept touch events with onInterceptTouchEvent(MotionEvent)
.
Touch Mode當使用者在使用方向鍵或軌跡球瀏覽使用者介面時,有必要給於一個焦點在可操作的組件上(如一個Button),使使用者可以看到它將接受輸入命令。如果裝置有觸摸功能,那麼,當使用者與介面的互動就不再需要有一個高亮在組件上,或一個焦點在view上,因此,模式的互動名為"觸摸模式"。對於一個觸摸裝置,一旦有使用者接觸螢幕時,該裝置將進入觸摸模式.在點觸某個View後,只有的它的方法isFocusableInTouchMode()返回為真時,才會有聚集焦點,如文本編輯工具。其他的介面只可以點觸,但不會聚集焦點(高亮),如button 被點觸時就不會聚集焦點,當它被按下時只會調用on-click監聽器的回調方法。
任何時候使用者接觸方向鍵或者滾動軌跡球時,該裝置將退出觸摸模式,並聚集焦點,使用者可以恢複與使用者介面的鍵盤互動,而不必在螢幕上。觸摸模式的狀態是由整個系統來維持的(all windows and activities),要查詢目前所處的狀態,你可以調用isInTouchMode()方法來獲得,看看裝置目前是否處於觸摸模式。
Handling Focus系統架構將處理日常的焦點移動來響應使用者的輸入,它包刮改變焦點(當介面是被移除,隱藏,或者作為一個新的View變為可用狀態),通過isFocusable()這個方法我們可以知道view是否具有接受焦點的資格,也可以通過setFocusable().來設定view接受焦點的資格,對應在觸摸模式下,你可以調用isFocusableInTouchMode().來獲知是否有焦點來響應點觸,也可以通過setFocusableInTouchMode().來設定是否有焦點來響應點觸的資格.
系統架構控制焦點移動到另一個組件的演算法是在某一方向上鄰近的組件,在極個別情況下,預設的演算法可能不符合開發人員的預想要求,在這種情況下,你可以覆寫下列XML屬性的布局檔案: nextFocusDown , nextFocusLeft , nextFocusRight ,和nextFocusUp 設定他們的值來明確
焦點從當前介面移動下個介面的Id。例如:
<LinearLayout android:orientation="vertical" ... > <Button android:id="@+id/top" android:nextFocusUp="@+id/bottom" ... /> <Button android:id="@+id/bottom" android:nextFocusDown="@+id/top" ... /> </LinearLayout>
一般來說,在這個垂直布局,瀏覽的焦點會從第一個按鈕開始,不會是從第二個或者其他的,現在topButtont已經通過nextFocusUp (反之亦然)確定了bottom.
通常如果你想宣布使用者介面具有焦點的資格 (如果這個介面在傳統上是沒有的),可以在xml布局裡去加上的android:focusable的屬性,並設定它的值,您也可以宣布在觸摸模式下具有焦點的資格,同樣也只在xml裡添android:focusableInTouchMode.的屬性,並設定它的值. 當使用者請求在某個介面聚集焦點時,會調用requestFocus().這個方法。監聽到焦點活動(獲得焦點或失去焦點都會被通知),會調用onFocusChange(),這個方法,這也是上節所討論的Event Listeners。
總結:
- 對於UI控制項事件的處理,需要設定相應的監聽器,並實現相應的事件處理常式。這兒有兩種實現方法:一是定義一個OnClickListener 類的執行個體,並使用setOnClickListener等綁定監聽器;二是用Activity去實現OnClickListener介面,並作為它的一部分,這樣會更方便,省去了載入額外的類和對象的時間。
- 對於支援觸控螢幕的手機,可以設定觸摸模式的UI,可以使用isInTouchMode()來獲得觸摸模式的狀態。
- UI處理的另一個重點是焦點的設定及其切換。焦點設定:通過setFocusable或者setFocusableInTouchMode設定可以接受焦點,通過isFocusable或isFocusableInTouchMode擷取是否可以接受焦點;焦點切換:編寫XML布局檔案的nextFocusDown 等屬性設定。
參考:http://developer.android.com/guide/topics/ui/ui-events.html
eoeAndroid社區組