Dialog的Window的创建过程和Activity的类似
1、创建Window
与Activity的一样同样是通过PolicyManager的makeNewWindow方法来完成,实际上就是PhoneWindow。
public class Dialog implements DialogInterface, Window.Callback,KeyEvent.Callback, OnCreateContextMenuListener {
Dialog(Context context, int theme, boolean createContextWrapper) {
if (theme == 0) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
outValue, true);
theme = outValue.resourceId;
}
mContext = createContextWrapper ? new ContextThemeWrapper(context, theme) : context;
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
}
2.初始化DecorView并将Dialog的视图添加到DecorView中
public void setContentView(int layoutResID) {
mWindow.setContentView(layoutResID);
}
3.将DecorView添加到Window中显示
Dialog的show方法,通过WindowManager将DecorView添加到Window中
mDecor = mWindow.getDecorView();
try {
mWindowManager.addView(mDecor, l);
mShowing = true;
sendShowMessage();
} finally {
}
以上可以看出 Dialog的Window的创建过程和Activity的Window的创建过程很类似。
当Dialog被关闭时,会通过WindowManager来移除DecorView
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
} else {
mHandler.post(mDismissAction);
}
}
void dismissDialog() {
if (mDecor == null || !mShowing) {
return;
}
if (mWindow.isDestroyed()) {
Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
return;
}
try {
mWindowManager.removeView(mDecor);
} finally {
if (mActionMode != null) {
mActionMode.finish();
}
mDecor = null;
mWindow.closeAllPanels();
onStop();
mShowing = false;
sendDismissMessage();
}
}
普通的Dialog有一个特殊之处,那就是必须采用Activity的Context,如果采用Application的Context,就会报错。报没有应用token的错误,而应用token一般只有Activity才有,所以只需要用Activity作为Context来显示对话框即可。系统Window比较特殊,它不需要token,如果想要指定对话框为系统Window类型,可以设置WindowManager.LayoutParams.type参数。
dialog.getWindow().setType(LayoutParams.TYPE_SYSTEM_ERROR)
同时不要忘记在AndroidManifest中添加权限。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />