轉:Android開發指南-用戶界面-事件處理

原帖地址:http://blog.csdn.net/iefreer/archive/2009/09/23/4586351.aspx

 

處理用戶界面事件Handling UI Events

Android上,不止一個途徑來偵聽用戶和應用程序之間交互的事件。對於用戶界面裏的事件,偵聽方法就是從與用戶交互的特定視圖對象截獲這些事件。視圖類提供了相應的手段。

在各種用來組建佈局的視圖類裏面,你可能會注意到一些公共的回調方法看起來對用戶界面事件有用。這些方法在該對象的相關動作發生時被Android框架調用。比如,當一個視圖(如一個按鈕)被觸摸時,該對象上的onTouchEvent()方法會被調用。不過,爲了偵聽這個事件,你必須擴展這個類並重寫該方法。很明顯,擴展每個你想使用的視圖對象(只是處理一個事件)是荒唐的。這就是爲什麼視圖類也包含了一個嵌套接口的集合,這些接口含有實現起來簡單得多的回調函數。這些接口叫做事件偵聽器event listeners,是用來截獲用戶和你的界面交互動作的“門票”。

當你更爲普遍的使用事件偵聽器來偵聽用戶動作時,總有那麼一次你可能得爲了創建一個自定義組件而擴展一個視圖類。也許你想擴展按鈕Button類來使某些事更花哨。在這種情況下,你將能夠使事件處理器event handlers類來爲你的類定義缺省事件行爲。

 

事件偵聽器Event Listeners

事件偵聽器是視圖View類的接口,包含一個單獨的回調方法。這些方法將在視圖中註冊的偵聽器被用戶界面操作觸發時由Android框架調用。下面這些回調方法被包含在事件偵聽器接口中:

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章節以獲取更多信息。

這些方法是它們相應接口的唯一“住戶”。要定義這些方法並處理你的事件,在你的活動中實現這個嵌套接口或定義它爲一個匿名類。然後,傳遞你的實現的一個實例給各自的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);

    ...

}

你可能會發現把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 表示你還沒有處理它和/或這個事件應該繼續交給其他on-click偵聽器。

·         onKey() 返回一個布爾值來指示你是否已經消費了這個事件而不應該再進一步處理它。也就是說,返回true 表示你已經處理了這個事件而且到此爲止;返回false 表示你還沒有處理它和/或這個事件應該繼續交給其他on-key偵聽器。

·         onTouch() 返回一個布爾值來指示你的偵聽器是否已經消費了這個事件。重要的是這個事件可以有多個彼此跟隨的動作。因此,如果當接收到向下動作事件時你返回false,那表明你還沒有消費這個事件而且對後續動作也不感興趣。那麼,你將不會被該事件中的其他動作調用,比如手勢或最後出現向上動作事件。

記住按鍵事件總是遞交給當前焦點所在的視圖。它們從視圖層次的頂層開始被分發,然後依次向下,直到到達恰當的目標。如果你的視圖(或者一個子視圖)當前擁有焦點,那麼你可以看到事件經由dispatchKeyEvent()方法分發。除了從你的視圖截獲按鍵事件,還有一個可選方案,你還可以在你的活動中使用onKeyDown() and onKeyUp()來接收所有的事件。

注意: Android 將首先調用事件處理器,其次是類定義中合適的缺省處理器。這樣,從這些事情偵聽器中返回true 將停止事件向其它事件偵聽器傳播並且也會阻塞視圖中的缺事件處理器的回調函數。因此當你返回true時確認你希望終止這個事件。

事件處理器Event Handlers

如果你從視圖創建一個自定義組件,那麼你將能夠定義一些回調方法被用作缺省的事件處理器。在創建自定義組件Building Custom Components的文檔中,你將學習到一些用作事件處理的通用回調函數,包括:

·         onKeyDown(int, KeyEvent) - 當一個新的按鍵事件發生時被調用。

·         onKeyUp(int, KeyEvent) - 當一個向上鍵事件發生時被調用。

·         onTrackballEvent(MotionEvent) - 當一個跟蹤球運動事件發生時被調用。

·         onTouchEvent(MotionEvent) - 當一個觸摸屏移動事件發生時調用。

·         onFocusChanged(boolean, int, Rect) - 當視圖獲得或者丟失焦點時被調用。

你應該知道還有一些其它方法,並不屬於視圖類的一部分,但可以直接影響你處理事件的方式。所以,當在一個佈局裏管理更復雜的事件時,考慮一下這些方法:

·         Activity.dispatchTouchEvent(MotionEvent) - 這允許你的活動可以在分發給窗口之前捕獲所有的觸摸事件。

·         ViewGroup.onInterceptTouchEvent(MotionEvent) - 這允許一個視圖組ViewGroup 在分發給子視圖時觀察這些事件。ViewParent.requestDisallowInterceptTouchEvent(boolean) - 在一個父視圖之上調用這個方法來表示它不應該通過onInterceptTouchEvent(MotionEvent)來捕獲觸摸事件。

觸摸模式Touch Mode

當用戶使用方向鍵或跟蹤球瀏覽用戶界面時,有必要給用戶可操作的item(比如按鈕)設置焦點,這樣用戶可以知道哪個item將接受輸入。不過,如果這個設備有觸摸功能,而且用戶通過觸摸來和界面交互,那麼就沒必要高亮items,或者設定焦點到一個特定的視圖。這樣,就有一個交互模式 叫“觸摸模式”。

對於一個具備觸摸功能的設備,一旦用戶觸摸屏幕,設備將進入觸摸模式。自此以後,只有isFocusableInTouchMode()爲真的視圖纔可以被聚焦,比如文本編輯部件。其他可觸摸視圖,如按鈕,在被觸摸時將不會接受焦點;它們將只是在被按下時簡單的觸發on-click偵聽器。任何時候用戶按下方向鍵或滾動跟蹤球,這個設備將退出觸摸模式,然後找一個視圖來接受焦點,用戶也許不會通過觸摸屏幕的方式來恢復界面交互。

觸摸模式狀態的維護貫穿整個系統(所有窗口和活動)。爲了查詢當前狀態,你可以調用isInTouchMode() 來查看這個設備當前是否處於觸摸模式中。

處理焦點Handling Focus

框架將根據用戶輸入處理常規的焦點移動。這包含當視圖刪除或隱藏,或者新視圖出現時改變焦點。視圖通過isFocusable()方法表明它們想獲取焦點的意願。要改變視圖是否可以接受焦點,可以調用setFocusable()。在觸摸模式中,你可以通過isFocusableInTouchMode()查詢一個視圖是否允許接受焦點。你可以通過setFocusableInTouchMode()方法來改變它。焦點移動基於一個在給定方向查找最近鄰居的算法。少有的情況是,缺省算法可能和開發者的意願行爲不匹配。在這些情況下,你可以通過下面佈局文件中的XML屬性提供顯式的重寫:nextFocusDownnextFocusLeftnextFocusRight, 和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>

通常,在這個豎向佈局中,從第一個按鈕向上瀏覽或者從第二個按鈕向下都不會移動到其它地方。現在這個頂部按鈕已經定義了底部按鈕爲nextFocusUp (反之亦然),瀏覽焦點將從上到下和從下到上循環移動。

如果你希望在用戶界面中聲明一個可聚焦的視圖(通常不是這樣),可以在你的佈局定義中,爲這個視圖增加android:focusable XML 屬性。把它的值設置成true。你還可以通過android:focusableInTouchMode在觸摸模式下聲明一個視圖爲可聚焦。

想請求一個接受焦點的特定視圖,調用requestFocus()

要偵聽焦點事件(當一個視圖獲得或者失去焦點時被通知到),使用onFocusChange(),如上面事件偵聽器Event Listeners一章所描述的那樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章