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

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

     

更多相关文章

  1. Android:控件的对象修改控件的值
  2. 【30篇突击 android】源码统计 十六
  3. android之datepicker控件用法
  4. Android——按钮类控件
  5. Android 控件抖动效果
  6. 使用Android studio导入源码工程
  7. Android中使用Animation实现控件的动画效果以及Interpolator和An
  8. Android Jetpack之Lifecycle的源码分析
  9. Android 源码启动虚拟机经验

随机推荐

  1. Android与PC通过USB连接通信(一)
  2. [转」android中的数据库操作
  3. Android四种Activity的加载模式
  4. Android(安卓)中文 API (34) ―― RadioGro
  5. Android联系人数据库全解析(1)
  6. android里面EditTex多行输入及输入置顶问
  7. android流式布局热门标签的实现
  8. 《Android(安卓)应用 之路》 MPAndroidCh
  9. Android(安卓)TextView内容过长加省略号,
  10. 安装Intel HAXM为Android(安卓)模拟器加