Android官方文檔—User Interface(Input Events)

輸入事件

在Android上,有多種方法可以攔截用戶與您的應用程序交互的事件。在考慮用戶界面中的事件時,方法是從用戶與之交互的特定View對象中捕獲事件。 View類提供了這樣做的方法。

在用於構成佈局的各種View類中,您可能會注意到幾種對UI事件有用的公共回調方法。當在該對象上發生相應的操作時,Android框架會調用這些方法。例如,當觸摸View(例如Button)時,將在該對象上調用onTouchEvent()方法。但是,爲了攔截它,您必須擴展類並重寫該方法。但是,爲了處理這樣的事件而擴展每個View對象是不切實際的。這就是爲什麼View類還包含一組嵌套接口,其中包含可以更容易定義的回調。這些稱爲事件偵聽器的接口是捕獲用戶與UI交互的門票。

雖然您將更常使用事件偵聽器來偵聽用戶交互,但是有時您可能希望擴展View類,以構建自定義組件。也許你想擴展Button類以使某些東西更加花哨。在這種情況下,您將能夠使用類事件處理程序爲您的類定義默認事件行爲。

事件監聽器


事件偵聽器是View類中的一個接口,它包含一個回調方法。當用戶與UI中的項目交互觸發了已註冊偵聽器的View時,Android框架將調用這些方法。

事件偵聽器接口中包含以下回調方法:

onClick()

從View.OnClickListener。當用戶觸摸項目時(當處於觸摸模式時)或者使用導航鍵或軌跡球聚焦在項目上並按下合適的“輸入”鍵或按下軌跡球時調用此方法。

onLongClick()

從View.OnLongClickListener。當用戶觸摸並保持項目時(當處於觸摸模式時)或者使用導航鍵或軌跡球聚焦於項目並按下並按住合適的“輸入”鍵或按下並按住軌跡球時(一秒鐘)。

onFocusChange()

從View.OnFocusChangeListener。當用戶使用導航鍵或軌跡球導航到項目或遠離項目時,會調用此方法。

onKey()

來自View.OnKeyListener。當用戶專注於該項目並按下或釋放設備上的硬件密鑰時,將調用此方法。

onTouch()

從View.OnTouchListener。當用戶執行限定爲觸摸事件的動作時調用此方法,包括按下,釋放或屏幕上的任何移動手勢(在項目的範圍內)。

onCreateContextMenu()

從View.OnCreateContextMenuListener。這是在構建上下文菜單時調用的(由於持續的“長按”)。請參閱菜單開發人員指南中有關上下文菜單的討論。

這些方法是其各自界面的唯一居民。要定義其中一個方法並處理事件,請在Activity中實現嵌套接口或將其定義爲匿名類。然後,將實現的實例傳遞給相應的View.set ... Listener()方法。 (例如,調用setOnClickListener()並將其傳遞給OnClickListener。)

下面的示例顯示瞭如何爲Button註冊一個on-click監聽器。

// 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實現爲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。
  • onKey() - 返回一個布爾值,表示您是否已經消耗了該事件,並且不應該進一步攜帶它。也就是說,返回true表示你已經處理了這個事件,它應該在這裏停止;如果您尚未處理它並且/或該事件應繼續到任何其他on-key偵聽器,則返回false。
  • onTouch() - 返回一個布爾值,指示您的偵聽器是否使用此事件。重要的是,此事件可以有多個相互跟隨的操作。因此,如果在收到向下操作事件時返回false,則表示您尚未使用該事件,並且對此事件的後續操作也不感興趣。因此,您不會在事件中調用任何其他操作,例如手指手勢或最終的上行動作事件。

請記住,硬件鍵事件始終傳遞到當前焦點的視圖。它們從View層次結構的頂部開始,然後向下調度,直到它們到達適當的目標。如果您的View(或您的View的子級)當前具有焦點,那麼您可以通過dispatchKeyEvent()方法查看事件。作爲通過View捕獲關鍵事件的替代方法,您還可以使用onKeyDown()和onKeyUp()接收Activity內的所有事件。

此外,在考慮應用程序的文本輸入時,請記住許多設備只有軟件輸入方法。這些方法不需要是基於密鑰的;有些人可能會使用語音輸入,手寫等。即使輸入方法呈現類似鍵盤的界面,它通常也不會觸發onKeyDown()系列事件。除非要將應用程序限制爲具有硬件鍵盤的設備,否則不應構建需要控制特定按鍵的UI。特別是,當用戶按下返回鍵時,不要依賴這些方法來驗證輸入;相反,使用IME_ACTION_DONE之類的操作來向輸入方法發出應用程序期望的反應信號,因此它可能會以有意義的方式更改其UI。避免假設軟件輸入方法應該如何工作,只要相信它就可以爲應用程序提供已經格式化的文本。

注意:Android將首先調用事件處理程序,然後調用類定義中的相應默認處理程序。因此,從這些事件偵聽器返回true將停止將事件傳播到其他事件偵聽器,並且還將阻止對View中的默認事件處理程序的回調。因此,請確保在返回true時終止事件。

事件處理程序


如果您正在從View構建自定義組件,那麼您將能夠定義幾個用作默認事件處理程序的回調方法。在有關自定義組件的文檔中,您將瞭解到一些用於事件處理的常見回調,包括:

  • onKeyDown(int,KeyEvent) - 在發生新的鍵事件時調用。
  • onKeyUp(int,KeyEvent) - 發生密鑰啓動事件時調用。
  • onTrackballEvent(MotionEvent) - 在軌跡球運動事件發生時調用。
  • onTouchEvent(MotionEvent) - 發生觸摸屏動作事件時調用。
  • onFocusChanged(boolean,int,Rect) - 在視圖獲得或失去焦點時調用。

您應該注意一些其他方法,這些方法不是View類的一部分,但可以直接影響您處理事件的方式。因此,在佈局中管理更復雜的事件時,請考慮以下其他方法:

  • Activity.dispatchTouchEvent(MotionEvent) - 這允許您的Activity在調度到窗口之前攔截所有觸摸事件。
  • ViewGroup.onInterceptTouchEvent(MotionEvent) - 這允許ViewGroup在將事件分派給子視圖時觀察事件。
  • ViewParent.requestDisallowInterceptTouchEvent(boolean) - 在父視圖上調用此方法以指示它不應使用onInterceptTouchEvent(MotionEvent)攔截觸摸事件。

觸摸模式


當用戶使用方向鍵或軌跡球導航用戶界面時,必須將焦點放在可操作的項目(如按鈕)上,以便用戶可以看到接受輸入的內容。但是,如果設備具有觸摸功能,並且用戶通過觸摸它開始與界面交互,則不再需要突出顯示項目或將焦點放在特定視圖上。因此,存在稱爲“觸摸模式”的交互模式。

對於具有觸控功能的設備,一旦用戶觸摸屏幕,設備將進入觸摸模式。從這一點開始,只有isFocusableInTouchMode()爲true的視圖纔是可聚焦的,例如文本編輯小部件。其他可觸摸的視圖,如按鈕,在觸摸時不會聚焦;他們只需在按下時觸發他們的點擊式聽衆。

每當用戶點擊方向鍵或使用軌跡球滾動時,設備將退出觸摸模式,並找到要獲得焦點的視圖。現在,用戶可以在不觸摸屏幕的情況下恢復與用戶界面的交互。

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

處理焦點


該框架將處理針對用戶輸入的例行焦點移動。這包括在刪除或隱藏視圖或新視圖可用時更改焦點。視圖表明他們願意通過isFocusable()方法獲得焦點。要更改View是否可以獲得焦點,請調用setFocusable()。在觸摸模式下,您可以查詢View是否允許使用isFocusableInTouchMode()進行焦點。您可以使用setFocusableInTouchMode()更改此設置。

焦點移動基於在給定方向上找到最近鄰居的算法。在極少數情況下,默認算法可能與開發人員的預期行爲不匹配。在這些情況下,您可以在佈局文件中提供以下XML屬性的顯式覆蓋:nextFocusDown,nextFocusLeft,nextFocusRight和nextFocusUp。將其中一個屬性添加到焦點所在的視圖中。將屬性的值定義爲應該給予焦點的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(反之亦然),導航焦點將從上到下和從下到上循環。

如果您想在UI中聲明View是可聚焦的(傳統上不是這樣),請在佈局聲明中將android:focusable XML屬性添加到View中。將值設置爲true。您還可以在觸摸模式下使用android:focusableInTouchMode將View聲明爲可聚焦。

要請求特定視圖獲得焦點,請調用requestFocus()。

要偵聽焦點事件(在View接收或失去焦點時收到通知),請使用onFocusChange(),如上面的Event Listeners部分所述。

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