Analysis of setContentView () method in Android Dialog, setcontentview
Overview
DialogIt is an excellent tool in Android. In useDialogWe usually customize the layout of the content to be displayed.DialogThree methods are provided to support custom content layout.
1 public void setContentView (int layoutResID);2 3 public void setContentView (View view);4 5 public void setContentView (View view, ViewGroup.LayoutParams params);
The internal implementation principles of these three methods are the same, but their encapsulation depth is different. The three methods take care of developers with different customization depths.
SetContentView () Process
ViewDialogAs shown in 1.
Figure 1]
MediumMWindowInDialogClass is defined as follows:
1 import android.view.Window;2 3 Window mWindow;
So where does it come from? See figure 2.
Figure 2]
From 2, we can see that in the constructionDialogObject, thisMWindowIs also determined. It consistsYymanager. Next, follow the system code.
MakeNewWindow (Context)The method is implemented as follows:
1 // The static methods to spawn new policy-specific objects2 public static Window makeNewWindow(Context context) {3 return sPolicy.makeNewWindow(context);4 }
Continue to follow up.
1 import com.andorid.policy.internal.policy.impl.Policy; 2 /** 3 * {@hide} 4 */ 5 public class Policy implements IPolicy { 6 //... 7 8 public Window makeNewWindow(Context context) { 9 return new PhoneWindow(context);10 }11 }
At this point, it seems like we have almost reached the end. The setContentView we called was implemented in this PhoneWindow class. Continue to follow up.
1 import com.android.internal.policy.impl.PhoneWindow; 2 /** 3 * Android-specific Window. 4 * <p> 5 * todo: need to pull the generic functionality out into a base class 6 * in android.widget. 7 */ 8 public class PhoneWindow extends Window implements MenuBuilder.Callback { 9 //...10 }
SetContentView (int)
The code implementation of this method is shown in 3.
Figure 3]
The entire implementation process is simple and clear at first glance. The layout parameter we passed in is finally loaded toMContentParent. ThisMContentParentIsViewGroupClass Object. In the code shown in the following code, Row 3 makes an empty judgment. It can be seen that the instance creation of this object is related to the installDecor () method. The implementation of this method is complicated. Here we only look at the mContentParent instantiation process.
Figure 4]
ThisGenerateLayout ()The implementation process of the method is complicated. We do not need to understand every line of code. You only need to know that it is in this way to create the mContentParent object ,. Finally, the contentParent is returned as the result. Then return to Figure 3. In the code shown in the figure, Row 3 loads the layout we passed in into the system container.
SetContentView (View) and setContentView (View, ViewGroup. LayoutParams)
In this way, the content layout is flexible. It is generally used for layout that requires special operations in Java code. For example, set a listener. The specific implementation code is shown in Figure 5.
Figure 5]
This code is nothing special, and its purpose has been clearly expressed in the code, so it will not be repeated.
SetContentView (View) cannot set layout size
UseSetContentView (int)In the root container of layoutSpecify width and heightTo set the layout size. Note that I am referring to the straightforward method of specifying the width in the Root View and the height in pixels to control the layout size. If it is setMATCH_PARENT, The effect is equivalentWRAP_CONTENT. Why is this? I did not go into the cause, but ISpeculation (and not confirmed later)This is unrelated to the process of re-determining the size of the entire view after the mContentParent loads the layout. Let's flip the ViewGroup code. In ViewGroup, there is a piece of code as shown in figure 6.
Figure 6]
For a ViewGroup and its subclass, itsMeasureSpecOr yesEXACTLYOr yesAT_MOSTI cannot remember the specific relationship between the headers here. But the code shown in Table 6 is already very straightforward. For MATCH_PARENT, it is indeed handled in the WRAP_CONTENT method. This explains the "puzzling" situation mentioned above. Although this is just my guess, I guess it is still.
And useSetContentView (View)Regardless of the width and height of the root container in layoutWRAP_CONTENT. Why? Let's look back at the implementation of this method in the code shown in Figure 5. It can be found that PhoneWindow provides a defaultViewGroup. LayoutParamsObject. And the value of width and height is unbiased.MATCH_PARENT. Therefore, regardless of the width and height of the root container in layout, this method is used to adapt the layout according to the content size. Therefore, if you want to control the size of the dialog box layout, you can honestly create a LayoutParams object with a specified width and height for the PhoneWindow object. Do not expect others to wipe your ass or clean it ~~
So here, let's take a simple look,SetContentView (int)How can we directly set the size. Let's go back to figure 3 and look at the implementation code of this method. There are 378th rows. When ing xml, the second parameter is passed directly to mContentParent. When we usually use the ing layout function, Let's explain the truth and pass a null parameter more often, or perhaps we seldom notice this parameter at ordinary times. Let's go to LayoutInflater for transfer.
1 import android.view.LayoutInflater;
The code of the inflate () method is still quite long. I will not describe it in detail here. Let's just pick a representative one.
1 public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) 2 3 // ... 4 5 final AttributeSet attrs = Xml.asAttributeSet(parser); 6 7 // ... 8 9 // Create layout params that match root, if supplied10 params = root.generateLayoutParams(attrs);11 12 // ...13 14 // Temp is the root view that was found in the xml15 final View temp = createViewFromTag(root, name, attrs, false);16 17 // ...18 19 if (root != null && attachToRoot) {20 root.addView(temp, params);21 }22 23 // ...
Clear enough. Here, LayoutInflater resolves all attributes when ing the xml layout. Of course, it includes the attributes of the outer container. Then, generate a LayoutParams object based on the parsing result. Finally, add the content layout to the mContentParent container together with the instantly created LayoutParams object. In fact, it is equivalent to calling setContentView (View, layoutParams) method. At the beginning of the article, I mentioned that the three methods for setting the content layout of Dialog are essentially the same, but their encapsulation depth is different.
Set the Dialog background to completely transparent
By default, Dialog has a gray background. The background is ugly, and the background also affects customization of the Dialog box UI.
In the Activity, you can input a Style of the non-Background Dialog box to the constructor when creating the Dialog to create a Dialog box without a gray background. You can also use Java code to control the background color of the dialog box to be transparent. You can also first show () dialog box, and then setContentView () to achieve the purpose of a dialog box without a background color.
1. Style
1 <style name="transBg" parent="@android:Theme.Dialog">2 <item name="android:windowBackground">@android:color/transparent"</item>3 </style>
1 AlertDialog dialog = new AlertDialog. builder (mContext, R. style. transBg ). create (); 2 // or 3 Dialog dlg = new Dialog (mContext, R. style. transBg); 4 // and so on
2. Java code control
The so-called background is actually the background of PhoneWindow. We only need to set the background of PhoneWindow to transparent to achieve what we want.
1 //... 2 AlertDialog dialog = builder. create (); 3 dialog. show (); 4 dialog. setContentView (view); 5 // method 1, using a transparent ColorDrawable object. 6 dialog. getWindow (). setBackgroundDrawable (new ColorDrawable (0); 7 // method 2, using a transparent Drawable image. 8 dialog. getWindow (). setBackgroundDrawableResource (R. drawable. transparent );
3. display the dialog box before setting the Layout
This method only works in Activity.
1 AlertDialog dialog = builder.create();2 dialog.show();3 dialog.setContentView(view);
As to why the Service is ineffective, I suspect that a dialog box can only be set as a system-level dialog box in the Service, resulting in more code. However, its principle has not been studied yet.
1 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
In Service. Background transparency can only be achieved through the above 1st and 2nd methods.
Now, I wish you good luck!