四种方式
区别
- Activity、Dialog的type都是TYPE_APPLICATION,PopupWindow是TYPE_APPLICATION_PANEL;
- Activity、Dialog中封装了PhoneWindow对象,PopupWindow没有;因此PopupWindow默认不获取焦点、不响应输入事件、不独占触摸事件、显示时不添加DimLayer。
- 创建Activity对话框需要额外与AMS通信,Dialog、PopupWindow不需要;
- Activity、Dialog只能修改WindowManager.LayoutParams.gravity,以定位到相对屏幕的位置;PopupWindow可以定位到相对于某个View的位置;
- 自定义入场/出场动画的方式不同。
补全PopupWindow
由于PopupWindow是TYPE_APPLICATION_PANEL,所以默认的PopupWindow的功能往往不能满足需求。
响应BACK事件
- 调用PopupWindow.setFocusable(true);
- 调用PopupWindow.setBackgroundDrawable(new ColorDrawable())。
响应软键盘输入事件
- 调用PopupWindow.setFocusable(true);
- 调用setSoftInputMode()设置软键盘行为;必须有PopupWindow.INPUT_METHOD_NEEDED。
点击背景消失
调用PopupWindow.setOutsideTouchable(true)。
添加DimLayer
创建ValueAnimator,在入场/出场时改变所属Activity的WindowManager.LayoutParams.dimAmount。
BadToken
在启动Activity时弹出对话框,常会出现BadToken的错误。关键是要防止在AMS向WMS申请到WindowToken前弹出。具体地说,有以下4种方式:
- 如果SDK >= 21且Activity有入场动画时,可以重写onEnterAnimationComplete();
- 可以重写onWindowFocusChanged();
- 可以添加ViewTreeObserver.OnWindowFocusChangeListener()回调;
- 可以添加ViewTreeObserver.OnGlobalLayoutListener()回调;