前幾天在重新翻看《第一行代碼》時,發現了很多因為之前偷懶沒有注意的東西,比如Listview中構建FruitAdapter時用到的inflate方法,去年學的時候一直沒去了解,這次打算學習一下,
LayoutInflater.java中inflate函式的定義為:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
這三個引數的意思是:
- resource :布局的資源id
- root :填充的根視圖
- attachToRoot :是否將載入的視圖系結到根視圖中
就像書上所說的,前兩個引數的意思就是將resource指定的布局添加到root中去,但第三個引數attachToRoot的含義他說的太過于模糊,如果只是為了不把他添加到父布局中,為什么不能直接把root設定為空值,
抱著試一試的想法,我把parent改成了null,但是運行的結果和之前沒有任何差別,
為了搞懂attachToRoot所帶來的影響,我建立了一個簡單的testInflate專案,
其中activity_main.xml內容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:layout_width="20dp"
android:layout_height="20dp"
android:gravity="center"
android:background="#E89C17"
/>
</LinearLayout>
另外新建了一個inflate.xml,內容如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@color/colorAccent"
android:gravity="center"
android:orientation="vertical">
<Button
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
MainActivity.java中的啟動函式寫為:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout test = (LinearLayout) findViewById(R.id.main);
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.inflate, test,true);
}
}
attachToRoot設定為true
首先我們先將attachToRoot設定為true,其他引數不變,運行結果如下:
很顯然成功的將inflate.xml作為子布局添加到activity_man.xml中,
那么如果不直接使用inflater.inflate()函式,而是賦值給一個view,將view傳入父布局中呢?所以可以將MainActivity函式改成如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout test = (LinearLayout) findViewById(R.id.main);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.inflate, test, true);
test.addView(view);
}
雖然專案可以運行,但是卻出現了秒退的現象,我們查看報錯資訊發現:

這說明當attachToRoot設定為true時,inflate方法中view的添加是自動實作的,這時我算是理解了《第一行代碼》中說的:將第三個引數指定為false,表示只是為了在父布局中宣告的layout屬性生效,但不為這個View添加父布局,因為一旦View有了父布局之后,他就不能再添加到ListView中,就是因為當attachToRoot設定為true時的自動添加,
如果我們將最后一行的 test.addView(view);刪掉,程式正常,
attachToRoot設定為false
將attachToRoot設定為false,其他引數不變,運行結果與attachToRoot為true時相同,可以想到的是當MainActivity.java代碼如下時(即attachToRoot設定為false,再將view添加到test中):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout test = (LinearLayout) findViewById(R.id.main);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.inflate, test, false);
test.addView(view);
}
程式正常,
root設定為null
那么如果直接將root設定為null,此時attachToRoot為何值都不會有影響,MainActivity.java代碼如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout test = (LinearLayout) findViewById(R.id.main);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.inflate, null, false);
test.addView(view);
}
運行結果為:

仔細看差別還是很大的,我在inflate.xml中設定的布局屬性,嚴謹的說是LinearLayout的屬性(我這里設定的長度和寬度)失效了,這是為什么呢?
在查閱資料后發現,當root不為null時,可以說是父布局充當了要添加的子布局的一個容器,當root為null時,表示我不需要將第一個引數所指定的布局添加到任何容器中,所以由于整個LinearLayout并沒有處于某一個容器中,所以它的根節點的寬高屬性會失效,但是因為里面的Button是從屬于inflate.xml的LinearLayout的,也就是說LinearLayout充當了Button的容器,所以Button的屬性可以顯示出來,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/205993.html
標籤:其他
