> 在用戶的交互中,有不止一種的方法來截獲事件??紤]到在用戶界面中的事件時,從特殊的與用戶交互的view對象中捕獲事件,View類提供了一些特殊的方法。 再各種的視圖類中,你要編寫自己的布局,你可以聲明一些公共的回調方法來響應UI事件。當相應的動作發(fā)生時,這些方法會被android框架自動調用。例如,當一個view被觸摸時,onTouchEvent()方法被調用。然而,為了截獲這些方法,我們需要重寫這些方法。當然了,重寫每一個這樣的方法顯然時不實際的,這就是為什么為何view類會有一些必須的接口這樣你可以更加容易的使用。這些接口,被稱作事件監(jiān)聽器 event listeners,這就是捕捉到界面上用戶操作的關鍵。 當你經常在用戶交互上使用事件監(jiān)聽器時,有時需要自己寫一個繼承自view的類,來自定義一個部件。如果你想繼承一個Button類來實現(xiàn)更多的功能,這種情況下,你可以借助event handlers 類來定義默認的事件處理類。 事件監(jiān)聽器是包含簡單回調方法的view類的一個接口,當用戶觸發(fā)了一些注冊過的事件時,android系統(tǒng)框架會自動調用相應的方法。 事件監(jiān)聽器包含以下幾個方法: onCLick() 來自View.onClickListener。 當view被觸摸,或者焦點在view上時,用戶按了確認鍵或導航鍵。 onLongClick() 來自 View.onLongClickListener。當view被觸摸超過1秒,或者焦點在view上,用戶按了確認或導航鍵超過1秒時,方法被調用。 onFocysChange() 來自 View.onFocusChangeListener。當焦點離開view時被調用。 onKey() 來自 View.onKeylistener。按下或者彈起某個鍵時方法被調用。 onTouch() 來自 View.OnTouchListener。當用戶操作屏幕時被調用,包括按下釋放或者其他的操作。 onCreateContextMenu() 來自 View.onCreateContextMenuListener。當一個Context Menu菜單被建立時調用。 這些方法都有自己的接口方法。如果想定義這些方法來處理自己的事件,只要在activity里面使用匿名類即可。然后使用View.setXXXListener()方法,將匿名類傳遞給view。 下面的例子演示了怎樣給一個Button注冊一個監(jiān)聽器:
- // 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);
...
}
復制代碼你會發(fā)現(xiàn)讓activity實現(xiàn)監(jiān)聽器接口是非常方便的,他可以讓你的程序避免多余的對象分配。 - [size=14px]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
}
...
} [/size]
復制代碼注意,上面例子中的onClick()回調方法沒有返回值,但其他的時間監(jiān)聽器必須返回一個boolean類型的返回值,這是由監(jiān)聽器的類型決定的,例如:onLongClick()這個方法會返回一個布爾值,來說明這個事件正在進行,也就是說,返回true表明此事件正在被處理不會被繼續(xù)傳遞了。onKey()也會返回一個布爾值,返回true的話說明此按鍵事件將會被處理并不會被繼續(xù)響應。如果你沒有處理或者希望事件繼續(xù)被其他監(jiān)聽器響應,那么返回false。onTouch()返回同上,也是返回true就不再被傳遞。重點是有很多類型的事件與這個事件有關,例如,當接收到鍵被按下的事件時,如果你此時返回false,那么表明你將不會處理這個按鍵事件。因此,你不會處理這個事件,例如手勢或者其他后續(xù)事件。記住這些按鍵事件總會讓當前veiw成為當前焦點,他們從view層次結構的頂端開始被一級級傳遞,直到到達應該被響應的地方。如果你的view或者子view當前擁有焦點,那么你可以看到事件怎樣傳遞到dispatchKeyEvent()方法。作為一種捕捉按鍵事件的替代方法,你可以接收activity里的所有的onKeyDown()和onKeyUp()事件。注意:Android會首先調用事件處理程序,然后再調用自定義的事件處理類。例如:返回true將會阻止事件被繼續(xù)傳遞給下一層,也會阻止系統(tǒng)做一些默認的處理,所以如果你確定要終止這個事件就返回true。 如果你創(chuàng)建了一個自定義的view組件,那么你要定義幾種回調方法來。在Building Custom Components文檔中,你會學習到以下幾個回調事件:onKeyDown(int,ketEvent);鍵被按下onKeyUp(int,keyEvent);鍵彈起onTrackballEvent(MotionEvent);軌跡球事件onTouchEvent(MotionEvent);觸摸屏幕事件onFocusChanged(boolean,int,Rect);焦點改變事件這里有一些你需要知道的方法,他們不是view類的一部分,但是會直接影響到你對事件的處理。所以遇到十分復雜的布局時,可以考慮以下的幾個方法:Activity.dispatchTouchEvent(MotionEvent)它允許你的activity攔截所有的觸摸事件ViewGroup.onInterceptTouchEvent(MotionEvent)允許VeiwGroup來觀察子view的事件ViewParent.requestDisallowInterceptTouchEvent(boolean)告訴父View不應該使用相關方法來攔截事件。
當用戶正在使用導航鍵或者軌跡球來與手機交互時,有必要給當前互動的item例如button一個焦點,來讓用戶看到接收輸入、或者說當前的控件。如果一個設備支持觸摸,那么操作時就不需要用上面的高亮顯示的方式來告訴用戶。因此,便有了這種觸摸模式。對于有觸摸功能的設備來說,一旦用戶觸摸了屏幕,設備便會進入觸摸模式。只有那些isFocusableInTouchMode()返回true的控件才可以獲得焦點,例如文本編輯框。別的view是touchable的,例如按鈕,但被點擊時不會顯示焦點。當被按下時,他們的事件監(jiān)聽器將會無效。任何時候用戶點擊了導航鍵或者軌跡球,設備都會退出touch模式,并且找一個view來顯示焦點。現(xiàn)在,用戶可以不用觸摸屏幕來與設備進行交互了。Touch模式存在于整個系統(tǒng)中。包括窗口和activity??梢杂胕sinTouchMode()方法來查詢當前模式。
框架會處理常規(guī)的焦點改變事件來響應用戶的輸入。包括一些veiw的顯示和隱藏。view通過isFocusable()方法來設定是否可以得到焦點。調用setFocusable()方法可以改變focusable狀態(tài)。當view在觸摸模式,你可以通過調用isFocusableInTouchMode()方法查詢到是否支持,通過setFocusableInTouchMode()來設置。焦點的運動是根據給定方向最近的一個view來確定的。在極少情況下,默認的這種算法或許不符合開發(fā)者預期的要求。這種情況下,可以通過xml來明確確定焦點的轉移情況。例如: - <LinearLayout
android:orientation="vertical"
... >
<Button android:id="@+id/top"
android:nextFocusUp="@+id/bOTTom"
... />
<Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
</LinearLayout>
復制代碼一般的,在垂直的布局里,往下或者往上移動軌跡球或是導航鍵多不能移動焦點,現(xiàn)在可以通過xml的定義來達到移動焦點的目的。如果你想要聲明可以獲得焦點的view,可以在xml里添加android:focusable這個屬性,設置為true,你也可以在Touch模式下添加android:focusableInTouchMode。使用requestFocus()方法可以使一個特定的師徒取的焦點。使用onFocusChange()方法來監(jiān)聽焦點事件。
|