dispatchTouchEvent → onInterceptTouchEvent → onTouchEventView.OnTouchListener.onTouch 優先於 onTouchEvent。onTouch 回傳 true 表示消費事件,**阻斷**後續 onClick。onTouch 回傳 false 表示不消費,**但必須在 ACTION_DOWN 回傳 true 才能收到後續 ACTION_MOVE/UP**。// 錯誤:ACTION_DOWN 回傳 false
@Override
public boolean onTouch(View v, MotionEvent event) {
return false; // 導致只有 DOWN,沒有 UP,onClick 不觸發
}
button.setOnTouchListener((v, event) -> {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
v.setPressed(true); // 視覺反饋
return true; // 關鍵:繼續接收 UP
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
v.setPressed(false);
// 執行點擊邏輯或讓 onClick 處理
return false; // 不消費,傳給 onClick
}
return false;
});
button.setOnClickListener(v -> {
// 正常觸發
});
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setPressed(true);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
setPressed(false);
performClick(); // 觸發 onClick
return true;
}
return super.onTouchEvent(event);
}
OnTouchListener.onTouch 在 ACTION_DOWN **必須回傳 true** 才能接收後續事件並讓 onClick 正常觸發。若需自定義按壓視覺效果,建議覆寫 onTouchEvent 並呼叫 performClick(),最符合 Android 事件分發規範。