Android LayoutInflater.inflate(R.layout.activity_test, container,false)参数解析

LayoutInflater.inflate()的功能:将一段 XML 资源文件加载成为 View

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
}

在源码中通过通过XmlResourceParser去解析xml获取xml信息,保存在parser这个对象里面,然后调用inflate(parser, root, attachToRoot)去添加这个资源文件下的view,构建一个view。

其中,对于inflate()函数传递不同参数分别有不同的效果:

  • inflate(layoutId, null ),则layoutId最外层控件通过layout_width和layout_height无效,因为这两个值是相对于父级确定的

      view的onMeasure方法:主要做的就是根据ViewGroup传入的测量模式和测量值,计算自己应该的宽和高:

      一般是这样的流程:

      如果宽的模式是AT_MOST:则自己计算宽的值。一般是wrap_content

       如果宽的模式是EXACTLY:则直接使用MeasureSpec.getSize(widthMeasureSpec);设置固定值或者match_parent

  • inflate(layoutId, root, false) 则 layoutId最外层控件的宽高设置正常,但在root里面不会显示
  • inflate(layoutId, root, true ) 则layoutId最外层的控件宽高会设置正常,并在root里面正常显示

接下来我们通过源码分析:

 final View temp = createViewFromTag(root, name, inflaterContext, attrs);

 通过上述代码,产生view控件。

                    View result = root;                   
                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // 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 against its context.
                    rInflateChildren(parser, temp, attrs, true);


                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }

由上述代码可知,当root不为null:

attachToRoot = false时,root生成的LayoutParams给当前temp,因此它的宽高是正常的

attachToRoot = true时,root生成的LayoutParams给当前temp,并且将view添加到root里面,因此它会在view里面显示出来

当root == null 或者 attachToRoot = false时,返回当前view,attachToRoot = true时返回的是root,所以当前显示的布局是root的话,这样才可以将view显示出来,否则view显示不出来。

举例分析:

public class TestActivity extends AppCompatActivity {

    private static final String TAG = "TestActivity";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      //  setContentView(R.layout.activity_test);
        LayoutInflater layoutInflater = LayoutInflater.from(this);
        View view1 = layoutInflater.inflate(R.layout.activity_test,null);
        Log.d(TAG,"Test view1 = " + view1+"view1: "+view1.getLayoutParams()+" ");
        View view2 = layoutInflater.inflate(R.layout.activity_test, (ViewGroup) findViewById(android.R.id.content),false);
        Log.d(TAG,"Test view2 = " + view2+" view2: "+view2.getLayoutParams()+" ");
        View view3 = layoutInflater.inflate(R.layout.activity_test, (ViewGroup) findViewById(android.R.id.content),true);
        Log.d(TAG,"Test view3 = " + view3+"view3: "+view3.getLayoutParams()+" ");
    }
}

布局文件:


运行效果:分别是view1,view2,view3

Android LayoutInflater.inflate(R.layout.activity_test, container,false)参数解析_第1张图片Android LayoutInflater.inflate(R.layout.activity_test, container,false)参数解析_第2张图片Android LayoutInflater.inflate(R.layout.activity_test, container,false)参数解析_第3张图片

打印的信息:

 D/TestActivity: Test view1 = android.support.v7.widget.AppCompatButton{6eb543a VFED..C.. ......I. 0,0-0,0 #7f070022 app:id/bt}view1: null 
 D/TestActivity: Test view2 = android.support.v7.widget.AppCompatButton{2c49cbc VFED..C.. ......I. 0,0-0,0 #7f070022 app:id/bt} view2: android.widget.FrameLayout$LayoutParams@ae03445 
 D/TestActivity: Test view3 = android.support.v7.widget.ContentFrameLayout{893c643 V.E...... ......I. 0,0-0,0 #1020002 android:id/content}view3: android.support.v7.widget.ActionBarOverlayLayout$LayoutParams@82604c0 

  • 注意点:
  • ListView当设置attachToRoot为true会崩溃,这是由于ListView是继承AdapterView的,而该View里面是不支持addView的,但是添加到root里面是通过addView方法(上述源码里有写)
  •   @Override
        public void addView(View child) {
            throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
        }

     

你可能感兴趣的:(Android,Studio,android)