实现对话框

共有Activity、Dialog、DialogFragment、PoppupWindow四种方式

Posted by candy1126xx on April 7, 2017

四种方式

区别

  • 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事件

  1. 调用PopupWindow.setFocusable(true);
  2. 调用PopupWindow.setBackgroundDrawable(new ColorDrawable())。

响应软键盘输入事件

  1. 调用PopupWindow.setFocusable(true);
  2. 调用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()回调;