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()+" ");    }}

布局文件:

<?xml version="1.0" encoding="utf-8"?>

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

打印的信息:

 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");    }

     

更多相关文章

  1. android map
  2. ScrollView嵌套webview因焦点问题导致自动滑动
  3. Android:控件的对象修改控件的值
  4. 设置TextView超过一定长度后显示省略号
  5. Android(安卓)去掉运营商STK对话框提示
  6. 【转】Android(安卓)kernel启动流程
  7. android之datepicker控件用法
  8. edittext 随文字换行 而高度增加
  9. Android(安卓)WebView相关属性

随机推荐

  1. WPS Office移动版(Android)限时免费,送小
  2. Android(安卓)将自己的Launcher设置为默
  3. Android(安卓)自定义数字键盘(一)
  4. 【构建Android缓存模块】(一)吐槽与原理分
  5. Android(安卓)nomedia 避免图片等资源泄
  6. windows下cygwin使用ndkr8编译ffmpeg
  7. 给android设备增加串口功能
  8. Android中进行图像压缩和缩放
  9. Android涔媋ndroid:layout_weight璇﹁В
  10. android 混淆规则详解