android的UI事件處理

在Android裏, 有不只一種方式可以截獲用戶與你的應用程序交互的事件. 在你的界面上處理事件時,你需要捕獲用戶與某個View實例交互時所產生的事件.View類支持這種做法.


在你佈局時需要使用的很多View類型裏,你應該注意到一些對處理UI事件很有用的公有回調方法. 當特定操作發生在一些指定對象的時候,Android系統的frmaework程序就會調用這些回調方法. 比如,當我們touch某個按鈕的時候,它的onTouchEvent()方法就會被調用. 但是, 爲了攔截這一過程,你必須繼承某個類並且重寫它的onTouchEvent()方法. 顯然,這樣處理所有View對象上觸發的事件是不切實際的.這就是爲什麼View類也包含了一組嵌套接口,它允許我們更加容易的定義自己想要的行爲. 這些接口,叫做事件監聽器,是你捕獲用戶與應用程序界面交互的關鍵所在.


在你總是使用事件監聽器來監聽用戶行爲的同時,哪一天你可能確實需要繼承某一個View類以建立一個自定義組件.這種情況下,你可以使用類裏所定義的事件處理器來爲你的類定義默認的事件處理行爲.

1.事件監聽器
一個事件監聽器就是View類裏一個包含單個回調方法的接口. 事件監聽器需要被註冊到某個View上,當用戶在界面上的操作觸發這個事件時,Android系統的frmaework程序就會調用這個監聽裏的回調方法.
包含在事件監聽器接口的回調方法有以下這些:


(1)onClick()----來自於 View.OnClickListener
當用戶touch the item (when in touch mode), 使用導航鍵將焦點置於此項並按下ENTER鍵 ,或者使用trackball選中此項並按下trackball時,這個方法會被調用.


(2)onLongClick()----來自於 View.OnLongClickListener
This is called when the user either touches and holds the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).


(3)onFocusChange()----View.OnFocusChangeListener
當用戶使用navigation-key或者trackball,將焦點切換到或者離開某個選項時,這個方法被調用.


(4)onKey()----來自於 View.OnKeyListener.
當用戶在焦點項上,按下或者釋放設備上某個鍵時,這個方法會被調用.


(5)onTouch()----來自於 View.OnTouchListener
This is called when the user performs an action qualified as a touch event, including a press, a release, or any movement gesture on the screen (within the bounds of the item).
參閱android.view.MotionEvent類的ACTION_CANCEL,ACTION_DOWN,ACTION_MOVE,ACTION_UP等字段.


(6)onCreateContextMenu()----來自於 View.OnCreateContextMenuListener.
當創建一個Context Menu的時候,這個方法會被調用.參閱Creating Menus文檔的context menu部分.

上述這些方法是它們各自接口的唯一內容.爲了定義它們中的任何一個來處理你的事件,需要使你的Activity實現某個接口,或者在某個匿名內部類裏定義接口的默認行爲.然後,傳遞你的實現方式的一個實例到相應的View.set...Listener()方法裏去.下面是創建一個匿名實現類的例子代碼段:
// 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);
    ...
}
當然還有另一種更方便的選擇,那就是把實現On...Listener作爲你的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()方法沒有返回值,但是有一些事件監聽器方法必須返回一個布爾值.這是根據事件本身而定的,我們來看看幾個有返回值的方法.
(1)onLongClick()方法.
它的返回值指示了你是否完成了事件處理工作並且要求事件就此終止而不再繼續向下傳遞.也就是說,返回true說明你已經處理了這個事件並且它應該就此終止;
返回false則說明你沒有處理事件,或者這個事件應該繼續被傳遞到其它的某個監聽上.


(2)onKey()方法.
同上.


(3)onTouch()方法.
同樣的,它的返回值指示你的listener是否處理了此事件.重要的是,這一事件可以有多個行爲,互相追隨(參閱android.view.MotionEvent類的ACTION_CANCEL,ACTION_DOWN,ACTION_MOVE,ACTION_UP等)。所以,如果你在down行爲的處理中返回了false,表明你還沒有處理事件並且對此事件裏的其它行爲也不感興趣.因此,你也不會收到此事件裏其它任何行爲的通知,比如用戶做的一個fingure手勢或者最終的up行爲時.

要記住,關鍵事件總是被分發到當前的焦點View.它們被派從頂部的View層次,然後下來,直到它們達到適當的終點。如果焦點在你的View(或者你的View的子元素)上,你可以看見被觸發的事件經過dispatchKeyEvent()方法.對於捕獲經過你的View的關鍵事件,還有一個替代方案,就是在你的Activity裏使用onKeyDown() 和 onKeyUp()方法.

注意:Android會首先調用事件處理器(View.on...Listener),然後纔會從類裏尋找合適的事件處理定義(View.onKeyDown等等[Activity.onKeyDown?????]).同樣的,從事件監聽器裏返回true將會打斷到其它監聽器的傳播,並且會阻塞View裏默認事件處理器的回調.所以,當你從事件監聽器裏返回true的時候,一定要小心,確認自己真的想要終止事件的處理和傳播.


2.事件處理程序
如果你正在使用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).

3.觸摸模式
當用戶正通過方向鍵或者trackball瀏覽界面時,我們需要把焦點設置到那些可操作的item上面,以使用戶明白哪裏處理它的請求. 但是,如果某個設備具備觸摸響應能力,用戶會直接通過觸摸來與應用程序交互,不再需要我們高亮顯示某個item或者爲某個view設置焦點了. 所以,我們稱這種交互模式爲觸摸模式.

對於一個有觸摸功能的設備來說,一旦用戶觸摸了屏幕,此設備立即進入觸摸模式. 從這點開始,只有那些isFocusableInTouchMode()爲true的View可以設置焦點,比如文本編輯widget.其它那些可觸摸的View,比如按鈕,被觸摸時也不會獲得焦點;它們只是在自己被pressed的時候簡單地激活on-click監聽器.

任何時候,一個用戶點擊一個方向鍵或用軌跡球滾動,該設備將退出觸摸模式,並把焦點設置到某個View上.現在,用戶可以恢復與沒有觸摸屏的用戶界面交互。

觸摸模式的狀態保持在整個系統(所有窗口和活動)。要查詢當前的狀態,你可以調用isInTouchMode(),看看是否該設備目前在觸摸模式。


4.處理焦點
該框架將處理響應用戶輸入過程中的例行焦點移動.包括在View被刪除或者隱藏` 新建View時改變焦點.Views通過isFocusable()方法表達它們獲取焦點的意願.如果要改變某個View能否接受焦點,調用setFocusable()方法.在觸摸模式下,你可以使用isFocusableInTouchMode()方法查詢某個View是否被允許設置爲焦點.同樣地,也有辦法改變這個屬性,調用setFocusableInTouchMode()方法就行.

確定下一個焦點的算法是尋找指定方向上的最近相鄰元素. 很少見的時候, 默認算法的結果不符合開發人員的預期行爲,這種情況下,可以通過下面幾個XML屬性明確指定焦點移動的結果:nextFocusDown, nextFocusLeft, nextFocusRight, and nextFocusUp. 添加這些屬性中的一個到焦點將要離開的View定義裏.把你想要下
一個focus的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定義了它的上方向鍵聚焦對象爲bottom(反過來也一樣),所以焦點會上下循環移動.

如果想在你的界面裏聲明一個可聚焦的View(當一般情況它不會被聚焦的時候), 添加android:focusable屬性到這個View定義裏去.把值設置爲true. 你也可以使用android:focusableInTouchMode屬性在觸摸模式下聲明一個可聚焦的View.

需要設置焦點到某個View時,調用requestFocus()方法.

爲了監聽聚焦事件(當一個View得到或者失去焦點的時候收到通知),使用onFocusChange()方法,就像上面"事件監聽器"部分所討論的那樣.


原文出自:http://hi.baidu.com/lck0502/blog/item/def374ddab8ccbe277c63815.html

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