安卓 Input Events(輸入事件)

在安卓中,有不止一種方法從你的應用截取用戶交互事件。在你的用戶界面中考慮事件,途徑就是從用戶界面中的一個指定的view對象中捕獲事件。該view提供了這樣作的方法。java

在你用來組成你佈局的不一樣的view類中,你或許注意到了一些公共的回調方法彷佛看起來對UI事件有用。這些方法由安卓的框架調用,當各自的操做在對象中發生時。例如,當一個view (一個按鈕)被觸摸,在這個對象中的onTouchEvent() 方法就會被調用。然而,爲了攔截這個事件,你必須繼承該類(button )而且重寫該方法(onTouchEvent)。然而,爲了處理這樣的一個事件而繼承每個view對象或許不實際。這就是爲何View 類常常包含一組嵌套的調用接口讓你能夠跟方便的定義(事件處理方法)。這些接口,叫作事件監聽者(  event listeners),用來捕獲用戶與UI的交互。
當你更加日常的爲你的用戶交互使用事件監聽者,當你想繼承一個view類,爲了建立一個自定義組件,或許可使用一次。或許你想要繼承 Button類來讓一些東西更加精美。在這樣的狀況下,你或許須要爲你的類定義一個默認事件行爲,使用該類的事件處理者( event handlers.).

 事件監聽者(Event Listeners)

一個事件監聽者是在view類中的一個接口,它包含了一個簡單的回調函數。這些方法將會被安卓框架調用,當該view的監聽者已經被註冊而且經過用戶ui 項被觸發。
包含了事件監聽者接口的都有以下回調方法:
onClick() 來自View.OnClickListener.。當用戶觸摸該item(觸摸模式下),或者使用導航鍵或軌跡球使焦點彙集在該項上而且按下了適當的"enter"(進入)按鍵或者在軌跡球上執行了按下操做。
onLongClick()來自  View.OnLongClickListener.。當用戶持續觸摸item時(觸摸模式下),或者使用導航鍵或軌跡球使焦點彙集在該項上而且持續按着適當的"enter"(進入)按鍵或者在軌跡球上執行持續按下操做(持續一秒)。
onFocusChange()來自  View.OnFocusChangeListener 當用戶使用導航鍵或者軌跡球導航到或者離開該item 時。
onKey() 來自View.OnKeyListener. 當用戶聚焦在了項目上而且按下或鬆開設備上的按鍵時
onTouch() 來自View.OnTouchListener.當用戶執行一個合格的觸摸操做,包括按下,釋放或者任何屏幕上的手勢動做(在項目的邊界內)
onCreateContextMenu() 來自View.OnCreateContextMenuListener. 當上下文菜單開始構建時調用(如持續「長按」的結果)。查看在  Menus開發嚮導中關於上下文菜單的討論。
這些方法是它們各自接口的惟一方法。爲定義其中的一個方法而且處理你的事件,在你的activity中實現嵌套的接口,或者做爲一個匿名類定義它。而後,傳遞一個你的實例引用給各自的View.set...Listener()方法。 method (例如,調用 setOnClickListener()而且傳遞一個你實例化的 OnClickListener
下面一個案例展現瞭如何爲一個按鈕註冊一個on-click監聽者。
// 爲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);
...
}
你能夠更加方便的找到實現OnClickListener ,做爲activity的一部分。這將會避免額外的類加載和對象分配。以下:
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,若是你沒有處理它或者該事件應該繼續傳遞給其它on-click監聽者。
  • onKey() - 該方法返回一個布爾類型來代表你是否消耗了該事件而且不該該進一步傳遞下去。也就是說,返回true代表你處理了該事件而且它應該在這停下來;返回false,若是你沒有處理它或者該事件應該繼續傳遞給其它on-click監聽者。
  • onTouch() - 該方法返回一個布爾類型來代表你是否消耗了該事件。重要的是該事件能夠有多個符合觸發條件的操做。所以,當按下事件被接受到,若是你返回了false,代表你沒有處理該事件而且對這個事件的後續行動不感興趣。所以,你不會爲每個操做都調用該事件,如手勢動做,或者最後的擡手動做(up action event)。
請記住,硬件按鈕事件老是傳遞給當前焦點視圖。從view的頂層開始向下分發,直到到達適當的地方。若是你的view(或者在view中的子view)得到了焦點,以後你能夠經過 dispatchKeyEvent()方法查看到事件的移動。做爲一個備選方法來從你的view中捕獲按鍵事件,你還能夠在你activity中的 onKeyDown() 和 onKeyUp().內收到各類事件。
而且,當你的應用輸入文本時,須要注意的是許多設備只有軟件的輸入方法。這些方法不須要按鍵支持,或使用聲音輸入,手寫,等等。即便一個輸入方法呈現了一個相似鍵盤的界面,它一般也不會觸發 onKeyDown()這類的事件。你永遠不該該建立UI來約束指定按鍵的按壓,除非你想要限制你應用使用設備的硬件盤。特別的,當用戶按下返回按鈕時,不要依賴於這些方法來確認輸入;改成使用像 IME_ACTION_DONE同樣的操做來代表該輸入方法而且讓你的應用程序作出怎樣的反應。這可能會以一種有意義的方式來改變它的UI。避免設想一個軟件輸入方法應該是如何工做的,而且只須要信任它來爲你的應用支持已經格式化的文本。
注意:安卓將會首先調用事件處理者,以後調用類中定義的適當的默認處理者。一樣的,從這些事件監聽者中返回true將會中止事件傳播給其它事件監聽者,而且阻塞view中的默認事件處理的回調。所以,當你返回true時,肯定你想要終止該事件。

 事件處理者(Event Handlers)

若是你想自定義一個view組件,那麼你可能會定義一些回調方法做爲默認的事件處理者來使用。在 Custom Components, 這篇文章中,你將會看到一些被用做事件處理的公共回調函數,包括:
這還有其餘的一些你須要注意的方法,它們不是view類的一部分,可是能夠直接影響你能處理事件的方式。所以,當在你的佈局中管理更多複合事件時,考慮這些方法:

 觸摸模式(Touch Mode)

當用戶使用方向鍵或軌跡球在用戶界面上移動時,給予活動項(如按鈕)焦點是必須的,這樣用戶能夠看見什麼輸入將會被接受。若是該設備有觸摸能力,而且用戶開始經過觸摸來與界面交互,那麼並不須要高亮顯示項目,或者給指定view 一個焦點。所以,有一個交互模式叫作「觸摸模式」(當今的安卓手機主要是該模式,因它沒有硬件輸入設備)
對於一個可觸摸的設備,移動用戶觸摸了屏幕,設備將會進入觸摸模式。今後刻開始,只有當view由於 isFocusableInTouchMode()爲true時纔可被聚焦,如文本編輯組件。其它view都是可觸摸的,如按鈕,在觸摸時將不會得到焦點;當按下時,他們僅僅的激活他們的on-click 監聽者。
任什麼時候候,用戶點擊一個方向鍵或滑動軌跡球,設備將會退出觸摸模式而且找到一個view使其得到焦點。如今,用戶能夠繼續與用戶界面交互,不使用觸摸屏幕這種方式。
觸摸模式狀態一直維持在整個系統中(全部Windows和activitys ).爲查詢當前狀態,你能夠調用 isInTouchMode() 來查看設備當前是否處於觸摸模式。

處理焦點(Handling Focus )

框架將會處理常規響應用戶輸入時的的焦點移動。這包括當view移除或隱藏時改變焦點,或一個新的view變爲可用。view經過 isFocusable()方法來代表他們得到焦點的意願。改變view是否能得到焦點,調用 setFocusable()。當處於觸摸模式,你或許須要經過 isFocusableInTouchMode()查詢一個view是否容許聚焦。經過使用 setFocusableInTouchMode()你能夠改變它。
焦點的移動是基於一個算法的,它順着一個給定的方向尋找最近的(view)。少數狀況下,默認算法或許不符合開發者的要求。在這種狀況下,你能夠提供詳細的覆蓋,經過在佈局文件中使用以下xml 屬性: nextFocusDown, nextFocusLeftnextFocusRight, 和  nextFocusUp。將其中的一個屬性添加到view上。該屬性的值是下一個須要獲取焦點的view的id。以下:
<LinearLayout
android:orientation="vertical"
... >
<Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
<Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
</LinearLayout>
一般,在該垂直佈局中,從第一個按鈕開始操縱(焦點)將不會跑去任何地方,若是從第二個按鈕開始操做,(焦點)也不會跑到它的下面去。如今頂部按鈕在底部定義了一個(按鈕)同nextFocusUp設置同樣(反之亦然),focus  焦點將會上-下 下-上的循環移動。
若是你想要在你UI中什麼一個view是可聚焦的(當它通常狀況下不是時),爲view添加 android:focusable xml屬性,在你的佈局文件中聲明。設置該值爲true。你也能夠聲明該view的可聚焦性,當在觸摸模式時經過 android:focusableInTouchMode.
爲請求一個特別的view得到焦點,調用 requestFocus()
爲監聽焦點事件(當一個view得到或失去焦點時通知),使用 onFocusChange(),在上文 #事件監聽者(Event Listeners)中討論的。
相關文章
相關標籤/搜索