Android LayoutInfater注入佈局 inflater()方法 引數講解
阿新 • • 發佈:2019-02-09
安卓如果要注入佈局 需要使用
LayoutInflater.from(context).inflate(resource,root,bollean);
這個方法的返回值是一個View 就是需要被注入到另一個佈局的View ,但是這個方法可以填三個引數 也可以複寫兩個引數,點開LayoutInflater原始碼,我們可以看到,這個類實際上是Android提供的以Pull形式來解析xml佈局檔案,下面通過分別呼叫這個方法的三種形式具體分析一下這三個引數的作用
首先畫一個需要被注入進的子佈局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/item" android:background="#f88" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="這個一個item" android:layout_width="wrap_content" android:layout_height="250dp" /> <Button android:text="這是item的按鈕" android:layout_width="wrap_content" android:layout_height="250dp" /> </LinearLayout>
這個item佈局的效果圖:
下面是Activity的佈局檔案 結構不復雜一個縱向的LinearLayout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linearlayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#05217b" android:orientation="vertical"> </LinearLayout>
1.三個引數第三個引數為true
在Activity中使用第一個方法
public class MainActivity extends AppCompatActivity { private LinearLayout linearlayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { linearlayout = (LinearLayout) findViewById(R.id.linearlayout); View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,linearlayout,true); } }
我們把第三個引數寫成True 返回了一View 並沒有向Activity中寫addView();方法
現在執行一下程式碼看到的效果:
也就是說我們剛剛畫的Item的View全部加入到了MainActivity中,並且指定了MainActivity的LinearLayout來作為itemView的根佈局
這個方法總結一下就是 直接將第一個引數的layout佈局檔案加進第二個引數的指定佈局(第二個引數的佈局將會作為第一個引數的根佈局),同時第一個引數的佈局檔案下面所有節點屬性全部有效
2.三個引數第三個引數為false
我們將剛剛MainActivity中的inflate方法第三個引數改為false,其他的不去改變,這個時候,我們再去執行一下程式碼,會發現佈局檔案並沒有被載入到第二個引數的佈局中.
因此我們需要加上addView();方法再執行一次
public class MainActivity extends AppCompatActivity {
private LinearLayout linearlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
linearlayout = (LinearLayout) findViewById(R.id.linearlayout);
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,linearlayout,false);
linearlayout.addView(itemView);
}
}
效果就跟第一個方法的效果一樣了
其實如果第三個引數我們設定為false的話 系統不會給我們直接給加載出來的view直接注入到第二個引數的根佈局中,需要我們再適當時候通過addView();方法將佈局進行注入.
3.兩個引數,第二個引數為空
下面將方法改為兩個引數,第二個引數設定空 並跑一下程式碼看一下效果
public class MainActivity extends AppCompatActivity {
private LinearLayout linearlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
linearlayout = (LinearLayout) findViewById(R.id.linearlayout);
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,null);
linearlayout.addView(itemView);
}
}
這回我們發現效果不一樣了,我的itemView明明設定的match_parent的屬性啊,為什麼不充滿MainActivity了呢? 那是因為我們第二個引數設定的是空 itemView最外層佈局不知道自己的根佈局是誰,通俗的說就是他找不到爸爸了 懵逼了,那他的match_parent屬性就失效了,可是他裡面包裹的子佈局知道自己的爸爸就是現在這個懵逼的爸爸,所以按鈕和文字的屬性有效...
那麼如果我不match_parent , 我直接給懵逼的佈局一個固定寬高呢?那麼我們再來試一下之後發現並沒有什麼卵用,高度依然不能鋪滿
總結一下第三個方法就是不給第一個引數設定根佈局,第一個引數的佈局檔案的最外層佈局屬性失效,因為找不到爸爸了所以失效了,需要用addView();方法將返回的View新增到想新增的佈局中.
其實如果看懂的小夥伴相信也明白了ListView在寫介面卡時候getView方法的使用了
最後
關於注入佈局所延伸出來的知識點,通過幾個大神的部落格自己也有所啟發:
1.我們在開發的過程中給控制元件所指定的layout_width和layout_height到底是什麼意思?該屬性的表示一個控制元件在容器中的大小,就是說這個控制元件必須在容器中,這個屬性才有意義,否則無意義。這就總結了第三個方法和前兩個的區別!
2.
為什麼Activity佈局的根節點的寬高屬性會生效?
其實原因很簡單,大部分情況下我們一個Activity頁面由兩部分組成(Android的版本號和應用主題會影響到Activity頁面組成,這裡以常見頁面為例),我們的頁面中有一個頂級View叫做DecorView,DecorView中包含一個豎直方向的LinearLayout,LinearLayout由兩部分組成,第一部分是標題欄,第二部分是內容欄,內容欄是一個FrameLayout,我們在Activity中呼叫setContentView就是將View新增到這個FrameLayout中.。而內容佈局就是一個FrameLayout,這個佈局的id叫作content,我們呼叫setContentView()方法時所傳入的佈局其實就是放到這個FrameLayout中的,這也是為什麼這個方法名叫作setContentView(),而不是叫setView()。