應用顯示一個非 Activity 類型的 Dialog,當其他應用彈出(如來電、系統彈窗)遮蓋該 Dialog 時,需要檢測並做相應處理(如暫停動畫、釋放資源)。
Dialog 繼承自 Window,可通過重寫 onWindowFocusChanged(boolean hasFocus) 監聽焦點變化:
public class MyDialog extends Dialog {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// Dialog 獲得焦點,處於最前端可見狀態
Log.d("Dialog", "顯示在最前端");
// 恢復動畫、重新註冊傳感器等
} else {
// Dialog 失去焦點,被其他窗口遮蓋或最小化
Log.d("Dialog", "被遮蓋/失去焦點");
// 暫停動畫、釋放獨佔資源等
}
}
}
若不想自定義 Dialog 類,可在 Activity 中設置 OnDismissListener 和 OnCancelListener,但這無法檢測「被遮蓋但未消失」的狀態。
dialog.getWindow().setCallback(new Window.Callback() {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// 同邏輯處理
}
// 其他回調方法需轉發給原 callback 或空實現
@Override public boolean dispatchTouchEvent(MotionEvent event) { return false; }
// ... 實現 Window.Callback 所有抽象方法
});
onWindowFocusChanged 在 Dialog **顯示/隱藏**、**被系統彈窗遮蓋/恢復**、**按 Home 鍵切回/切出** 等場景均會觸發。WindowManager 類型判斷或無障礙服務,複雜度較高。onWindowFocusChanged,處理焦點失去/獲得時的資源釋放/恢復。onPause/onResume 更可靠地感知可見狀態。通過 onWindowFocusChanged 可滿足絕大多數「感知 Dialog 是否最前端可見」的業務場景。