美文网首页
Dialog与PopWindow的区别

Dialog与PopWindow的区别

作者: Zcurry | 来源:发表于2018-12-27 18:01 被阅读0次

    其中最本质的差别:
    AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;
    而PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。
    这两种区别的表现是:AlertDialog弹出时,背景是黑色的,但是当我们点击背景,AlertDialog会消失,证明程序不仅响应AlertDialog的操作,还响应其他操作,其他程序没有被阻塞,这说明了AlertDialog是非阻塞式对话框;PopupWindow弹出时,背景没有什么变化,但是当我们点击背景的时候,程序没有响应,只允许我们操作PopupWindow,其他操作被阻塞。

    源码分析

    1. Dialog

    从dialog的源码可以看出,一个dialog的创建就是一个window的创建;而Activity也是一个window,所以在onCreate中调用dialog的show方法可以弹出,因为两个window是相互独立的,dialog的弹出不会触发Activity的生命周期;
    并且源码中可以看出,dialog默认是点击空白取消的,并位于居中位置。
    源码:

    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);
    }
    

    2. PopWindow

    从源码来看PopWindow的DecorView是PopupDecorView,PopupDecorView是继承
    FrameLayout,所以本质上PopupWindow就是一个View,需要依附一个具体的view,
    默认情况下是不能够在onCreate时显示;所以如果想要在界面显示的时候就弹出PopupWindow
    需要重写onWindowFocusChanged方法,判断activity完全显示,并且已经拿到焦点,此时
    才能进行显示;
    否则会报出异常:
    android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

    private void preparePopup(WindowManager.LayoutParams p) {
        ...
        mDecorView = createDecorView(mBackgroundView);
        mDecorView.setIsRootNamespace(true);
        ...
    }
    /**
     * Wraps a content view in a FrameLayout.
     *
     * @param contentView the content view to wrap
     * @return a FrameLayout that wraps the content view
     */
    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;
    }
    
    private class PopupDecorView extends FrameLayout {
           ...
    }
    

    其他

    1. PopWindow显示前需要设置宽高;Dialog不需要;
    2. PopWindow默认不会响应物理返回键;Dialog会在点击back键时消失;
    3. PopWindow不会给界面其他部分添加蒙层;Dialog会;
    4. PopWindow没有标题;Dialog默认有标题;

    相关文章

      网友评论

          本文标题:Dialog与PopWindow的区别

          本文链接:https://www.haomeiwen.com/subject/nrjdlqtx.html