介绍常见inflate方法
在日常开发中经常会用到通过资源id去获取view的场景,我们通常有四种方式去获取view,分别是以下四种:
//1,通过系统服务获取布局加载器
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(resource,root,attachToRoot);
//2,通过activity中的getLayoutInflater()方法
View view = getLayoutInflater().inflate(resource,root,attachToRoot);
//3,通过View的静态inflate()方法
View view = View.inflate(resource,root,attachToRoot);
//4,通过LayoutInflater的inflate()方法
View view = LayoutInflater.from(this).inflate(resource,root,attachToRoot);
通过对上述方法的源码的分析,很容易看出来这些方法都是最终调用了方式1,获取系统布局加载器的方式,来进行获取`View`。
这里我列举的并没有`inflate(int resource, ViewGroup root)`这个重载方法,是因为他们最终都会到调用为`inflate(int resource, ViewGroup root, boolean attachToRoot)`方法,如下:
public View inflate(int resource, ViewGroup root) {
return inflate(resource, root, root != null);
}
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
这里要说明一下,其实最终要调用的是`inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)`方法,只不过这里把布局资源解析为了XmlPull解析器,这里就不针对`XmlPullParser`进行研究了。
针对传入的参数不同进行分析
通过对`inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)`方法的源码进行解读,`XmlPullParser parser`是对传入`int resource`的xml解析器,不用去主要考虑,那就需要考虑传入`ViewGroup root, boolean attachToRoot`的值不同,会出现什么结果呢?源码中有几个重要的代码块:
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// 如果root不等于null,获取它的LayoutParams
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
//attachToRoot等于false,把root的LayoutParams属性给temp
temp.setLayoutParams(params);
}
}
//attachToRoot等于true,将temp加入到root这个viewGroup中
if (root != null && attachToRoot) {
root.addView(temp, params);
}
// root等于null,attachToRoot等于false,直接把temp赋值给返回结果
if (root == null || !attachToRoot) {
result = temp;
}
根据不同的传值进行实现
两个布局文件,一个作为root,一个作为我们的要获取的view
activity_my.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyActivity">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="120dp"
android:background="@color/blue">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello inflate"
android:textColor="@android:color/white" />
</LinearLayout>
1,rootView等于null,attachToRoot等于false
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = getLayoutInflater().inflate(R.layout.view, null, false);
setContentView(view);
}
本身root为null,就不会去获取view的LayoutParams,直接走`result = temp;`返回result,此时result等于view
为什么会充满屏幕呢,因为当把view设置到activity的视图时,系统会取当前window的LayoutParm作为view的LayoutParm
2,rootView等于null,attachToRoot等于true
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = getLayoutInflater().inflate(R.layout.view, null, true);
setContentView(view);
}
root等于null,依然走`result = temp;`,此时result等于view
为什么会充满屏幕呢,因为当把view设置到activity的视图时,系统会取当前window的LayoutParm作为view的LayoutParm
3,rootView不等于null,attachToRoot等于false
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rootView = getLayoutInflater().inflate(R.layout.activity_my, null);
view = getLayoutInflater().inflate(R.layout.view,(ViewGroup)rootView,false);
setContentView(view);
}
root不等于null,attachToRoot等于false,会走取view的LayoutParams并且赋值给temp,再走`result = temp;`,此时result等于view
为什么会充满屏幕呢,因为当把view设置到activity的视图时,系统会取当前window的LayoutParm作为view的LayoutParm
4,rootView不等于null,attachToRoot等于true
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rootView = getLayoutInflater().inflate(R.layout.activity_my, null);
view = getLayoutInflater().inflate(R.layout.view,(ViewGroup)rootView,true);
setContentView(view);
}
rootView不等于null,attachToRoot等于true,会首先获取view的Params,再走`root.addView(temp, params)`,也就是,把view先放入的root这个ViewGroup中,再返回result,因为初始化的时候result就等于root,此时返回的就是包含有子View的root。
这里因为root的布局为RelativeLayout,我们把view加入到root中,view本身保留了自有的LayoutParm
最后我要吐槽,为什么csdn不支持markdown,我都是先用Mou写好的,贴过来竟然要自己重新排版。。。