-
相同点
都是弹框; 都有默认背景,都可以通过setBackgroundDrawable(new ColorDrawable(android.R.color.transparent))去掉
-
不同点
基本不同: 1. popupwindow需要在显示之前设置宽高,Dialog则不需要。 2. popupwindow默认不会响应物理键盘,除非显示设置了popup.setFocusable(true),Dialog在点击back键时会消失。 3. popupwindow不会给界面其他部分添加蒙版,Dialog会。 4. popupwindow没有标题,dialog有默认标题。 5. 二者显示的时候都要设置Gravity。如果不设置,Dialog默认是Gravity.CENTER。
核心不同: 差别 Dialog是非阻塞式对话框:Dialog弹出时,后台还可以做事情。 PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有当我们调用了dismiss方法的后,PopupWindow退出后程序才会继续执行。 表现: Dialog弹出时,背景是黑色的,当我们点击背景Dialog会消失,程序不仅响应了Dialog的操作,也响应了其他的操作,因此其他程序没有被阻塞,所以Dialog是非阻塞式对话框。 PopupWindow弹出时,背景没有什么变化,但是当我们点击背景的时候,程序没有响应,只允许我们操作PopupWindow,其他操作被阻塞。 原理: 从dialog的源码可以看出,一个dialog的创建就是一个window的创建;而Activity也是一个window,所以在onCreate中调用dialog的show方法可以弹出,因为两个window是相互独立的,dialog的弹出不会触发Activity的生命周期; PopupWindow的DecorView是PopupDecorView,PopupDecorView是继承FrameLayout,所以本质上PopupWindow就是一个View,需要依附一个具体的view,默认情况下是不能够在onCreate时显示;所以如果想要在界面显示的时候就弹出PopupWindow需要重写onWindowFocusChanged方法,判断activity完全显示,并且已经拿到焦点,此时才能进行显示
-
源码
Dialog
核心: final Window w = new PhoneWindow(mContext)
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == ResourceId.ID_NULL) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//核心
final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setOnWindowSwipeDismissedCallback(() -> {
if (mCancelable) {
cancel();
}
});
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
popupWindow
在createDecorView方法中,需要传递一个View对象
/** View that handles event dispatch and content transitions. */
private PopupDecorView mDecorView;
private class PopupDecorView extends FrameLayout
private PopupDecorView createDecorView(View contentView) {
final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
final int height;
if (layoutParams != null && layoutParams.height == WRAP_CONTENT) {
height = WRAP_CONTENT;
} else {
height = MATCH_PARENT;
}
final PopupDecorView decorView = new PopupDecorView(mContext);
decorView.addView(contentView, MATCH_PARENT, height);
decorView.setClipChildren(false);
decorView.setClipToPadding(false);
return decorView;
}
- 使用场景
popupwindow特点是定位更加准确,对于宽高和边界的限制更加清晰,所以比较适合用作于一个Tips的提示。
Dialog相对于更加独立,相当于一个新的界面,或者是用作应用程序中的Loading界面