Cause Analysis of ineffective settings on the Root Node layout_width or layout_height of the xml file
In android development, I believe everyone is familiar with ListView, GridView, and other components. When using them, you need to configure relevant adapters by yourself, in addition, the xml file of the current backbone is configured as a child View formed by ListView. These xml files are called in the getView method of the Adapter. For example:
public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null) { convertView = App.getLayoutInflater().inflate(R.layout.item, null); } return convertView; }
The item. xml file is as follows:
The above method will show that the running effect is always the same regardless of the layout_width and layout_height of the Root View, that is, RelativeLayout; that is to say, it is not feasible to change the size of the Image View in the face through RelativeLayout. Generally, the solution is to add a View inside to wrap the ImageView, you can change the size of the ImageView by setting the size of the View (note that it is not necessarily an ImageView, or it may contain several views ):
Although I found a solution, I still need to know why. Why? A conceptual problem should be clarified before analysis:
Layout_width is not width! Layout_height is not height! That is to say, these two attributes are not set the width and height of the View. layout indicates the layout, that is, the width and height of the View in the layout! Since it is a layout, there must be a place to place the View, that is, there is a media to place the View, and the size of layout_width and layout_heigth on the media to place the View. Where is the layout of the media View not available? The root cause of the above problem is that you have not set a layout medium for the xml file (this medium is also a View, that is, rootView), so to ensure your item. the layout_width and layout_heigth of the Root View in xml can work. You need to set such a media. In the Code inflate (int, ViewGroup root), this root is such a medium, but it usually passes null, So item. the Root View of the xml file does not have a media basis for layout, so it does not work. Since the cause of the problem is found, you can use a stupid method to solve this problem: provide a root for inflate. In the code, I simply processed it and verified my thoughts:
Public View getView (int position, View convertView, ViewGroup parent) {if (convertView = null) {convertView = App. getLayoutInflater (). inflate (R. layout. item, null); // manually set a root. In this case, setting layout_width or layout_height will take effect in convertView = App. getLayoutInflater (). inflate (R. layout. item, (ViewGroup) convertView);} return convertView ;}
This method is used because it parses the item twice in xml, because inflate calls twice. Of course, the item at this time is:
Since it is related to the second inflate parameter root, let's take a look at what root has done. The method code for tracing the source code to parse xml is as follows:
// Remember, "root" is null, and "attachToRoot" is "root" in the source code! = Null, so here it is falsepublic View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot) {synchronized (mConstructorArgs ){...... view result = root; // The root View, Which is null try {.... final String name = parser. getName (); // node name. if it is a custom View, it is a fully qualified name. // This if statement does not need to be viewed for now if (TAG_MERGE.equals (name) {// Process
Tag ...} else {// Temp is the root view that was found in the xml // This is the root View corresponding to the xml file, in item. the xml file is RelativeLayout View temp = createViewFromTag (name, attrs); ViewGroup. layoutParams params = null; // because root = null, if condition is not true if (root! = Null) {// Create layout params that match root, if supplied // obtain a LayoutParams instance based on the AttributeSet attribute, remember that the caller is root. Params = root. generateLayoutParams (attrs); if (! AttachToRoot) {// reset the LayoutParams of temp // Set the layout params for temp if we are not // attaching. (If we are, we use addView, below) temp. setLayoutParams (params) ;}/// Inflate all children under temp // traverse all child nodes in temp, that is, View rInflate (parser, temp, attrs); // Add the root node of the xml file and the view of the child nodes in the root node to the root node, of course, if the root value is null, It is not executed here if (root! = Null & attachToRoot) {root. addView (temp, params);} // if the root node is null, View if (root = null |! AttachToRoot) {result = temp ;}}... return result ;}}
By analyzing the above code, we can find that when the root is null, inflate directly returns the View generated by the xml file, and the returned View root View is the root node of the xml file. At this time, the View does not have any layout, so the layout_height and layout_width of the root node are not attached to the media, resulting in invalid setting of these two attributes. However, if the root is not null, the View returned by inflate is such a View. First, parse the xml into a View, and then pass the View through the root. add addView to root, and then directly return to root. That is to say, the layout_width and layout_height of the root node in the xml file are the width and height of the layout in the root node, so these two attributes are effective at this time.
Note: In the Activity, we often call setContentView (int layoutResourceId) to set the View of the Activity. Why are the layout_width and layout_height values of the root nodes of these xml files effective? The following analysis shows that setContentView actually calls the inflate method to parse the xml file:
// There is a window reference in the Activity. In the Activity's setContentView, window is called. setContentView. The reference points to the PhoneWindow object. The code in this section is the code in the PhoneWindow class @ Override public void setContentView (int layoutResID) {if (mContentParent = null) {// mContentParent will be initialized in this method to ensure that it will not be null installDecor ();} else {mContentParent. removeAllViews () ;}// you are familiar with the code here. The Code is the same as in the Adapter above, but root is not null at this time !!!! MLayoutInflater. inflate (layoutResID, mContentParent); final Callback cb = getCallback (); if (cb! = Null) {cb. onContentChanged ();}}
One mContentParent is found in this method. First, determine whether mContentParent is null. If it is null, it will be initialized in the installDecor () method, that is, mContentParent can always be initialized, then the inflate (layoutResId, mContentParent) method is called. The second parameter in inflate that represents root is mContentparent and is not null. Then execute this method to parse the xml file, and finally execute the above inlfate (XmlPullParser, root, attachToRoot) method. According to the above analysis, therefore, we can conclude that setting layout_width or layout_height for the xml root node in the Activity is effective!