LayoutInflater那些事兒

對於android初學者而言,看到LayoutInflater只能說是“愛過“。在自定義控件的時候構造函數中會LayoutInflater.from(mContext).inflater(layout_id, this);還有重寫
適配器佈局會LayoutInflater.from(getContext()).inflater(layout_id, null);當時我也是隻知道這樣用,具體怎麼回事不是太清楚,今天就事論事,聊一聊LayoutInflater那些事兒。


首先我們要知道獲取LayoutInflater實例有三種方式,並且本質都是一樣的:

  1. LayoutInflater inflater = getLayoutInflater(); //調用Activity的getLayoutInflater()
  2. LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  3. LayoutInflater inflater = LayoutInflater.from(context);

讀過源碼的就會知道,三種最後都會執行到mContext.getSystemService()。

額,再來說說inflater方法,這個方法重載過一次,有兩種形式:

  1. inflater(int resource, ViewGroup root);
  2. inflater(int resource, ViewGroup root, boolean attachToRoot);

然而第一種方法本質是inflater(int resource, ViewGroup root, root != null);所以這兩個也是有聯繫的。

實踐出真理,寫個小demo,新建兩個佈局文件:
activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="#555"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="測試"
        android:textColor="#abc"
        android:textSize="40sp" />

</LinearLayout>

test.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="250dp"
    android:layout_height="match_parent"
    android:background="#478"
    android:orientation="vertical">

</LinearLayout>

非常簡單的兩個佈局,然後我們在MainActivity中編寫:

View test = getLayoutInflater().inflate(R.layout.test, null);
setContentView(test);

運行程序:

這裏寫圖片描述

發現寬和高並不是我們自己定義的250dp,是不是巧合咧,改下代碼:

View main = getLayoutInflater().inflate(R.layout.activity_main, null);
setContentView(main);

這裏寫圖片描述

呀哈,這就奇了怪了,爲什麼有這種情況,不要急,細細道來。

網上看源碼分析的demo一搜幾個G,我就不扯了,inflater(int resource, ViewGroup root, boolean attachToRoot)三個參數的意義:

  1. resource:不說也知道,佈局的id
  2. root:該視圖的根佈局
  3. attachToRoot:是否將該視圖添加到根佈局中並返回

inflater的視圖寬高,只有匹配到root根佈局纔會正常計算,不信你去看源碼,反正我是信了。
只看解釋可能沒有什麼說服力,那我們再修改代碼:

View main = getLayoutInflater().inflate(R.layout.activity_main, null);
View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main);
setContentView(test);

這裏寫圖片描述

首先inflater一個main佈局,因爲root傳的null所以寬高並不是我們自己定義的寬高,然後inflater一個test佈局,這個佈局傳的root是main佈局,後面的attachToRoot我沒寫出來,大家都應該知道是true吧,所以會正確的加載test佈局,並把test佈局添加到main佈局中並返回。

有疑問,沒關係,我們將

View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main);

改成

View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main, false);

按照上面的說法這裏還是會正確加載test佈局,但並不會將test添加到main佈局中,我們再運行看看:
這裏寫圖片描述

的確是這樣,證明了我們上述的猜測是對的。

好了,如果你一行一行地看到了這裏,相信你也明白了十之八九,好了,不知道大家有沒有遇到一個問題,在自定義adapter中listview不能正常顯示item的寬高,當初爲了這個抓破頭皮屑。。最簡單的解決方法就是在不要穿root爲空值,記得後面的參數傳false哦。

可能見解看法有偏差,虛心接受大牛們的評教。

發佈了30 篇原創文章 · 獲贊 21 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章