LayoutInflater技术广泛应用于需要动态添加View。
使用代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (LinearLayout) findViewById(R.id.main_layout);
LayoutInflater layoutInflater = LayoutInflater.from(this); // LayoutInflater初始化,传递上下文
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null); // inflate把布局和父布局联系起来,null代表没有父布局,只是单纯获得xml的布局
mainLayout.addView(buttonLayout); // xml的布局add到外部布局中
}
源码分析:
inflate()方法是核心方法,不论调用哪个重载方法,最终都会到inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
中。
这个方法的参数XmlPullParser为:
根据layout_id拿到对应的xml文件,转为XmlPullParser。
这个方法做的事情:
1、把XmlPullParser用XmlPull进行解析;
2、解析的结果传入createViewFromTag(),最终是通过反射调用createView()返回一个View;
3、rInflate()再把子标签挨个createViewFromTag()再add到view中;
4、最终返回view
补充点:
inflate(int resource, ViewGroup root, boolean attachToRoot)第三个参数的意义。
假设自己写的控件的xml为:
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="Button" >
</Button>
如果此时layoutInflater.inflate(R.layout.button_layout, null),那么无论layout_width还是layout_height改成多少,
这个空间的长宽不会改变。
原因:
layout_width的含义是“外部布局_宽度”的意思,就是说如果layout_width的标签也就是Button,没有一个外部布局,
那么这个Button的layout_width就无效。
这也是为什么叫做layout_width而不是叫做width的含义。
解决方式:
方法1:layoutInflater.inflate(R.layout.button_layout, 传入一个外部布局);
方法2:layoutInflater.inflate(R.layout.button_layout, 传入一个外部布局);
在Button外增加一个外部布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:layout_width="500dp"
android:layout_height="800dp"
android:text="Button" >
</Button>
</RelativeLayout>
此时就生效了,但是RelativeLayout的layout_width和layout_height又无效了。
方法3:layoutInflater.inflate(R.layout.button_layout, 传入一个外部布局, false);
这个代表Button不添加到外部布局中,但是layout_width和layout_height生效。
这里也就是引申出第三个参数的含义,true代表Button添加到外部布局且layout参数生效;
false代表Button不添加到外部布局且layout参数生效。
这里还有注意点,如果外部布局存在还传了true,那么后面不要再调用addView了,这样会抛出异常,
因为“true代表Button添加到外部布局且layout参数生效”,这里已经添加外部布局了,重复add,会抛出“一个view有多个父view”的异常。
**一句话总结:**第三个参数为false可以让layout参数生效,前提是存在第二个参数。true也生效,但是view必须添加在外部布局了。