1. 程式人生 > >Android官方文件—User Interface(Input Events)

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部分所述。