在做自定義彈窗的時候遇到的問題,如果不繼承Dialog 或者popwindow 自己寫的通過 getWindow的decorView 給decorView view 動態添加View 和移除View實現彈窗會出現返回按鍵如果是彈窗情況下需要關閉彈窗(即移除View) ,那么怎么監聽返回按鍵?這里看了dialog 和popwindow 發現了寫規律,即兩者都實現了Window.Callback,以及 KeyEvent.Callback, 這里KeyEvent.Callback有三個實現方法:
onKeyUp :抬起
onKeyLongPress:長按
onKeyDown:按下
而Window.Callback,就比較多了,這里我就不解釋了,主要說兩個地方:
dispatchKeyEvent :分發關鍵事件(這里指的就是home鍵盤,或者返回鍵,以及音量鍵,電源鍵等這些是關鍵事件)
dispatchTouchEvent:分發觸摸事件,這里是分發觸摸事件
如果想攔截手機的返回按鍵則需要在彈窗展示的時候讓窗口window 處理callback到這里,
即window.setCallback( );是自己的這個回調,不然一直都是Activity在處理按鍵,以及觸摸事件
1.在show的時候activity.getWindow().setCallBack(this) 自己的實現
2.然后重寫 dispatchKeyEvent 讓處理分發
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (xWindow.superDispatchKeyEvent(event)) { return true; } return event.dispatch(this, xWindow.getDecorView() != null ? xWindow.getDecorView().getKeyDispatcherState() : null, this); }
3.分發后就到了KeyEvent.CallBack的onKeyDown按下事件
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { event.startTracking(); return true; } return false; }
4.按下事件處理過后就是抬起,這里就判斷如果當前在展示,就關閉彈窗(移除View),然后消耗本次事件
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) { if (isShowing) { dismiss(); return true; } return false; } return false; }
5.關閉彈窗后不要忘記把窗體的回調還給Activity 的Callback
xWindow.setCallback(Activity);
6.到此為止關於按鍵就處理完了,但是還有問題,Callback不僅僅處理按鍵,還處理了觸摸事件,如果不做處理
那么在屏幕觸就無效了,無論怎么觸摸都沒響應,主要是因為
dispatchTouchEvent沒做處理,這里還需要做處理:
@Override public boolean dispatchTouchEvent(MotionEvent event) { if (xWindow.superDispatchTouchEvent(event)) { return true; } return false; }
到這里位置就全部處理完畢了
上文中代碼 xWindow變量就是從Activity中gewindow()獲取到的window對象
