生成LayoutInflater實(shí)例:
// 方法1
LayoutInflater mInflater = LayoutInflater.from(context);
// 方法2
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
最常用加載布局的方法:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
...省略實(shí)現(xiàn)代碼...
}
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
...省略實(shí)現(xiàn)代碼...
}
直接放上結(jié)論并驗(yàn)證講解:
閱讀源代碼可知:
- inflate(resource, null);
只創(chuàng)建view,view沒(méi)有LayoutParams值,然后直接返回view.
xml布局中最外層的layout_width、layout_height將失效. - inflate(resource, null, true);
同1. - inflate(resource, null, false);
同1. - inflate(resource, root);
創(chuàng)建view,然后執(zhí)行root.addView(view, params),最后返回root.
params為父布局根據(jù)xml布局中的寬和高得到相應(yīng)的LayoutParams - inflate(resource, root, true);
同4. - inflate(resource, root, false);
創(chuàng)建view,然后執(zhí)行view.setLayoutParams(params),然后返回view.
params為父布局根據(jù)xml布局中的寬和高得到相應(yīng)的LayoutParams
總結(jié)如下:
- 如果root為null,attachToRoot將失去作用,設(shè)置任何值都沒(méi)有意義,加載的布局文件最外層的所有l(wèi)ayout屬性會(huì)失效,由父布局來(lái)重新指定.
- 如果root不為null,attachToRoot不論是true或false,加載的布局文件最外層的所有l(wèi)ayout屬性都有效,唯一的不同是:
attachToRoot為true時(shí),會(huì)自動(dòng)調(diào)用root.addView(view, params),最后返回root;
attachToRoot為false時(shí),會(huì)返回view,需手動(dòng)調(diào)用root.addView(view, params). - 在不設(shè)置attachToRoot參數(shù)的情況下,如果root不為null,attachToRoot參數(shù)默認(rèn)為true.
廢話(huà)不多說(shuō),直接上代碼,首先定義三個(gè)xml:
main.xml - 此布局為父布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#519C9A"
android:orientation="vertical" />
item1.xml - 此布局高度固定
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="#C5C1AA"
android:gravity="center"
android:text="我是內(nèi)容"
android:textStyle="bold" />
item2.xml - 此布局高度自適應(yīng)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A4A4A4">
<TextView
android:layout_width="100dp"
android:layout_height="50dp"
android:background="#C9C9C9"
android:gravity="center"
android:text="我是內(nèi)容"
android:textStyle="bold" />
</RelativeLayout>
1. 如果root為null,attachToRoot將失去作用,設(shè)置任何值都沒(méi)有意義,加載的布局文件最外層的所有l(wèi)ayout屬性會(huì)失效,由父布局來(lái)重新指定.
content.addView(mInflater.inflate(R.layout.item1, null));
content.addView(mInflater.inflate(R.layout.item1, null, true));
content.addView(mInflater.inflate(R.layout.item1, null, false));

content.addView(mInflater.inflate(R.layout.item2, null));
content.addView(mInflater.inflate(R.layout.item2, null, true));
content.addView(mInflater.inflate(R.layout.item2, null, false));

小伙伴們看到這里是不是感覺(jué)暈暈的,明明item1.xml和item2.xml中根布局設(shè)置的寬度不是match_parent,結(jié)果卻是充滿(mǎn)屏幕寬?
在上面我們指出:這種方法的調(diào)用只是根據(jù)xml布局創(chuàng)建了view,view沒(méi)有設(shè)置LayoutParams值,而是在父布局調(diào)用addView(...)方法時(shí)給定params,下面給出代碼:
addView(...)方法是在ViewGroup.java中:
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
因?yàn)槲覀冞@里父布局root是LinearLayout,所以params變量是由調(diào)用了LinearLayout.java中的generateDefaultLayoutParams()方法生成
protected LayoutParams generateDefaultLayoutParams() {
// 水平布局下 寬度高度自適應(yīng)
if (mOrientation == HORIZONTAL) {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// 豎直布局下 寬充滿(mǎn)屏幕,高度自適應(yīng)
} else if (mOrientation == VERTICAL) {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
return null;
}
看到這里有沒(méi)有一種恍然大悟的感覺(jué)!
2. 如果root不為null,attachToRoot不論是true或false,加載的布局文件最外層的所有l(wèi)ayout屬性都有效,唯一的不同是:
attachToRoot為true時(shí),會(huì)自動(dòng)執(zhí)行root.addView(view, params),最后返回root;
attachToRoot為false時(shí),會(huì)返回view,需手動(dòng)調(diào)用執(zhí)行root.addView(view, params).
// 情景1 - attachToRoot為true
mInflater.inflate(R.layout.item1, content, true);
mInflater.inflate(R.layout.item2, content, true);
// 情景2 - attachToRoot為false
content.addView(mInflater.inflate(R.layout.item1, content, false));
content.addView(mInflater.inflate(R.layout.item2, content, false));
情景1和情景2任選一個(gè)運(yùn)行得到的結(jié)果如下:

3. 在不設(shè)置attachToRoot參數(shù)的情況下,如果root不為null,attachToRoot參數(shù)默認(rèn)為true.
直接上源碼,一目了然:
public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
return inflate(parser, root, root != null);
}
至此,文章結(jié)束,希望此文能幫助到你,如果對(duì)此文有不同見(jiàn)解,歡迎直接評(píng)論!
參考文檔:
關(guān)于LayoutInflater的錯(cuò)誤用法
Android LayoutInflater原理分析,帶你一步步深入了解View(一)
Android應(yīng)用setContentView與LayoutInflater加載解析機(jī)制源碼分析