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()+" "); }}
布局文件:
<?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"); }
更多相关文章
- Android:控件的对象修改控件的值
- 【30篇突击 android】源码统计 十六
- android之datepicker控件用法
- Android——按钮类控件
- Android 控件抖动效果
- 使用Android studio导入源码工程
- Android中使用Animation实现控件的动画效果以及Interpolator和An
- Android Jetpack之Lifecycle的源码分析
- Android 源码启动虚拟机经验