在android上, 有多種方法獲取用戶與應用程序的交互信息. 當考慮UI內部的事件時, 咱們的方法是抓取特定的與用戶交互的View對象產生的事件. android
在你用來組成佈局的View對象中,你可能會注意到一些用於處理UI事件的回調函數. 這些方法是被Android框架調用的. 例如,當一個View被按下時, 它的onTouchEvent()方法被調用. 可是,爲了截獲這個信息,你必須擴展這個類並改寫這個方法. 而擴展每一個View對象來處理這樣的事件多是不實際的. 這就是爲何View類還包含一組你能夠更方便定義的嵌套接口. 這些接口被稱爲監聽器, 它們是你用來抓取用戶動做的利器. 算法
雖然你可能更加經常使用事件監聽器來監聽用戶動做, 有時候你可能確實但願經過擴展一個View類的方法來作這一點. 可能你但願擴展Button類來作一些巧妙的事情. 在這個狀況下, 你可以使用時間處理器來定義該類的默認的事件行爲. 框架
一個事件監聽器是View類的一個接口. 該接口包含的方法會在View註冊的事件監聽器被觸發時被Android調用. 函數
在事件監聽器中有下列方法: 佈局
這些方法只是它們對應接口的惟一方法. 爲了定義這些方法, 能夠在你的Activity中實現這個接口, 也可使用一個匿名類. 而後, 將實現該接口實例傳給對應的View.set...Listener方法. ui
以OnClickListener爲例: this
// 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);
...
} spa
你可能以爲將OnClickListener 實現爲activity的一部分會更加方便. 這能夠避免額外的類. 例如: .net
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
}
...
} component
注意 onClick() 沒有返回值, 但有些事件監聽器必須有一個布爾返回值. 下面是一些緣由:
鍵事件永遠會被髮送到當前得到焦點的View. 它們是從View層次的頂端開始分派, 而後向下直到合適的目的地. 若是你的View如今擁有焦點, 那麼你能夠從dispatchKeyEvent()方法中看到事件的分派過程. 除了使用veiw以外,你也可使用你的Activity的onKeyDown()和onKeyUp()方法來獲取全部的時間.
注意: Android將首先調用事件處理器, 而後調用合適的默認處理器. 所以, 從這些事件監聽器中返回true將使其它監聽器和默認處理器失效. 所以在你返回true時要當心.
若是你從View來建立一個自定義的component,那麼你能夠定義一些默認事件處理器。在 Building Custom Components文檔中,你將看到這些回調函數:
有一些不屬於View,可是也能直接影響到事件處理的方法:
但一個用戶使用方向鍵或者軌跡球來在UI上移動時, 須要讓可動做的UI元素得到焦點, 這樣用戶能夠看到什麼東西將得到他們的輸入。若是設備具備觸摸能力,用戶使用觸摸的方式來交互,那麼就沒有必要給一個元素焦點。所以,有一種交互的模式叫作「觸摸模式」。
對於一個可觸摸的設備,一旦用戶觸摸了屏幕,設備就進入觸摸模式。在這之後,只有isFocusableInTouchMode()爲真的View是能夠得到焦點的, 例如文本框。其它的View能夠觸摸,例如按鈕,在觸摸的時候不會得到焦點。它們只是啓動對應的on-click監聽器。在用戶按下方向鍵或者旋轉軌跡球時,設備將退出觸摸模式,並尋找一個view並使他得到焦點。如今,用戶能夠不觸摸屏幕來交互。
觸摸模式狀態在整個系統中被維護。你可使用isInTouchMode()來查詢當前狀態。
android框架會根據用戶輸入來處理焦點的移動。這包含了在View被移除或隱藏或再次出現時改變焦點。View使用isFocusable()和setFocusable()方法來表示和設置它們可否得到焦點。在觸摸模式下,可使用isFocusableInTouchMode()和setFocusableInTouchMode().。
焦點移動時基於在某方向上最近距離元素的算法。在不多見的情形下,默認的算法可能和開發者的想法不同。在這種狀況下,你能夠提供一個算法,修改如下幾個xml屬性:nextFocusDown, nextFocusLeft, nextFocusRight和 nextFocusUp. 例如:
<LinearLayout
android:orientation="vertical"
... >
<Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
<Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
</LinearLayout>
通常來講,在這個豎直向下的佈局中,從第一個按鈕向上不會走到哪裏。加入上述代碼後,從第一個按鈕向上會使第二個按鈕獲取焦點。
若是你但願將一個View設爲可獲取焦點,那麼加入xml屬性android:focusable="true" 和android:focusableInTouchMode = "true".
但願一個View得到焦點時,調用requestFocus().
要監聽焦點事件,使用onFocusChange()。