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