1. 程式人生 > 其它 >Android Dialog 為什麼設定大小需要在 setContentView 方法之後

Android Dialog 為什麼設定大小需要在 setContentView 方法之後

Dialog設定大小為什麼需要在setContentView方法之後?

Dialog設定大小實際也是通過 WindowManager.LayoutParams 中的width,height屬性控制

但是我們看到Dialog內部關聯的Window(PhoneWindow)的WindowManager.LayoutParams的width,heigh預設值都是MATCH_PARENT,可當我們setContentView之後就變成了WRAP_CONTENT了呢?帶著疑問我們我們追蹤原始碼

首先看到Dialog預設關聯的Window

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
        //...省略
        final Window w = new PhoneWindow(mContext);
        //...省略
    }

PhoneWindow 繼承Window

Window的WindowManager.LayoutParams預設構造(width,height都是 MATCH_PARENT)

接著在看為什麼setContentView之後會變了呢

    @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        //首次執行這裡為空所以條件滿足
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

繼續跟進 installDecor 方法

其中 generateDecor() 方法建立 mDecor 裡面方法跟我們的大小沒有關係 ,我們重點看 generateLayout 方法

這裡我們已經看到大小被修改為了WRAP_CONTENT,但是有個限制就是mIsFloating是否為true

接著我們在驗證mIsFloating的值是如何來的

在上圖我們看到mIsFloating是解析WindowStyle來的,好的那我們跟進去看

解析 R.styleable.Window 屬性

檢視我們自己的dialogStyle樣式發現windowIsFloating預設值true

所以可以得出當使用Dialog並且樣式中有 <item name="android:windowIsFloating">true</item> 時,在setContentView方法之後會重置我們的width,height屬性

分析原始碼得出我們要修改Dialog尺寸時需要在setContentView方法之後