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方法之後