在做自定义弹窗的时候遇到的问题,如果不继承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对象