應用包含發送文本(彈出鍵盤)和語音播放按鈕。給根 View 設置 OnTouchListener 點擊空白處隱藏鍵盤,導致點擊播放按鈕時需點擊兩次:第一次隱藏鍵盤,第二次才觸發按鈕點擊事件。
在 Activity 中統一攔截觸摸事件,判斷觸摸點是否落在 EditText 區域外,若是則隱藏鍵盤,並確保事件繼續分發給目標 View(如按鈕)。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
// 關鍵:必須返回 super 分發,否則所有 View 都收不到 touch 事件
return super.dispatchTouchEvent(ev);
}
/**
* 判斷觸摸點是否在 EditText 區域外
*/
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && v instanceof EditText) {
int[] leftTop = {0, 0};
v.getLocationInWindow(leftTop);
int left = leftTop[0], top = leftTop[1];
int bottom = top + v.getHeight(), right = left + v.getWidth();
// 觸摸點在 EditText 矩形區域內 → 不隱藏鍵盤,保留 EditText 點擊事件
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true; // 區域外 → 隱藏鍵盤
}
}
return false; // 非 EditText 聚焦 → 不處理
}
dispatchTouchEvent 是事件分發的入口,在此攔截可全局控制。getLocationInWindow() 獲取 EditText 在窗口中的絕對位置,構建矩形區域。(event.getX(), event.getY()) 是否在矩形內,決定是否隱藏鍵盤。OnTouchListener,一勞永逸。此方案為 Android 開發中處理鍵盤與點擊衝突的標準最佳實踐。