View 類內建嵌套介面 Event Listeners,每個介面對應一種使用者互動:
| 介面 | 回調方法 | 觸發條件 | 回傳值意義 |
|---|---|---|---|
| OnClickListener | onClick(View) | 點擊/按下確認鍵 | 無 |
| OnLongClickListener | onLongClick(View) | 長按 1 秒以上 | true=消費事件,false=繼續傳遞 |
| OnFocusChangeListener | onFocusChange(View, boolean) | 焦點進入/離開 | 無 |
| OnKeyListener | onKey(View, int, KeyEvent) | 硬體按鍵按下/釋放 | true=消費 |
| OnTouchListener | onTouch(View, MotionEvent) | 觸控按下/移動/釋放 | true=消費後續事件 |
| OnCreateContextMenuListener | onCreateContextMenu(...) | 長按產生選單 | 無 |
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) { /* 處理邏輯 */ }
});
public class MainActivity extends Activity implements View.OnClickListener {
@Override protected void onCreate(Bundle saved) {
button.setOnClickListener(this);
}
@Override public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1: /* ... */ break;
}
}
}
自訂 View 時可覆寫預設處理器:
onKeyDown/Up(int, KeyEvent)onTouchEvent(MotionEvent)onTrackballEvent(MotionEvent)onFocusChanged(boolean, int, Rect)isFocusableInTouchMode()=true 的元件(如 EditText)可聚焦,Button 不再獲取焦點,僅觸發 onClickView.isInTouchMode() 查詢當前模式setFocusable(true/false)、setFocusableInTouchMode()nextFocusUp/Down/Left/RightrequestFocus() 主動請求焦點// ACTION_DOWN
mPrivateFlags |= PRESSED;
if (LONG_CLICKABLE) postCheckForLongClick(); // 500ms 後檢查長按
// ACTION_UP
if (PRESSED) {
boolean focusTaken = requestFocusIfNeeded();
if (!mHasPerformedLongPress) {
removeCallbacks(mPendingCheckForLongPress);
if (!focusTaken) performClick(); // 觸發 onClick
}
}
ACTION_DOWN/UP 先到達 onTouchEvent,再由框架判斷是否觸發 performClick() → onClick 或 performLongClick() → onLongClickonTouchEvent、onClick、onLongClick 並不互斥,視回傳值與邏輯決定onTouch 回傳 true 表示消費事件,後續 ACTION_MOVE/UP 不再傳遞給該 View 的 onTouchEventonClick/onLongClick 是框架基於 ACTION_DOWN/UP 時序合成出的高層語義事件Activity.dispatchTouchEvent(MotionEvent)
→ ViewGroup.dispatchTouchEvent()
→ ViewGroup.onInterceptTouchEvent() // true=攔截,false=分發給子 View
→ Child.dispatchTouchEvent()
→ Child.onTouchEvent()
ViewGroup.onInterceptTouchEvent:父容器決定是否攔截(如 ScrollView 滑動攔截)ViewParent.requestDisallowInterceptTouchEvent(true):子 View 要求父容器不攔截setOnClickListener 等最簡潔,避免繼承 ViewonTouchEvent 或用 GestureDetectoronTouch 返回 true 代表「我處理完了,別再傳了」