Android下LayoutInflater的正確使用姿勢(shì)

生成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)證講解:
閱讀源代碼可知:
  1. inflate(resource, null);
    只創(chuàng)建view,view沒(méi)有LayoutParams值,然后直接返回view.
    xml布局中最外層的layout_width、layout_height將失效.
  2. inflate(resource, null, true);
    同1.
  3. inflate(resource, null, false);
    同1.
  4. inflate(resource, root);
    創(chuàng)建view,然后執(zhí)行root.addView(view, params),最后返回root.
    params為父布局根據(jù)xml布局中的寬和高得到相應(yīng)的LayoutParams
  5. inflate(resource, root, true);
    同4.
  6. inflate(resource, root, false);
    創(chuàng)建view,然后執(zhí)行view.setLayoutParams(params),然后返回view.
    params為父布局根據(jù)xml布局中的寬和高得到相應(yīng)的LayoutParams
總結(jié)如下:
  1. 如果root為null,attachToRoot將失去作用,設(shè)置任何值都沒(méi)有意義,加載的布局文件最外層的所有l(wèi)ayout屬性會(huì)失效,由父布局來(lái)重新指定.
  2. 如果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).
  3. 在不設(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ī)制源碼分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 身為Android開(kāi)發(fā)者,我們知道在用RecycleView在onCreateViewHolder方法里通常...
    真_深紅騎士閱讀 2,074評(píng)論 0 1
  • 原文地址: http://allenfeng.com/2017/02/24/how-android-layout-...
    zizi192閱讀 383評(píng)論 0 1
  • RecyclerView Item 布局寬高無(wú)效問(wèn)題探究 前言 這個(gè)問(wèn)題很早之前就碰到過(guò),后來(lái)通過(guò)google找到...
    TinyMen閱讀 468評(píng)論 0 0
  • 大家對(duì)LayoutInflater一定不陌生,它主要用于加載布局,在Fragment的onCreateView方法...
    凡諾依曼閱讀 15,768評(píng)論 4 26
  • 有段時(shí)間沒(méi)寫(xiě)博客了,感覺(jué)都有些生疏了呢。最近繁忙的工作終于告一段落,又有時(shí)間寫(xiě)文章了,接下來(lái)還會(huì)繼續(xù)堅(jiān)持每一周篇的...
    justin_pan閱讀 597評(píng)論 0 2

友情鏈接更多精彩內(nèi)容