其實通過inflate從xml加載的view,被動態的添加到其他視圖中,view的layout_xx屬性是否有效,關鍵在於,加載完後,view的LayoutParam屬性是否和xml中的layout_xx屬性一致。因爲當系統無法計算view的layout_xx屬性時,view 的LayoutParam是空的,所以在addView的時候,系統會設置一個默認的LayoutParam,導致我們xml中設置的屬性失效。
下面介紹爲何view的layout_xx何時失效:
在這裏我們將我們需要從佈局文件加載的視圖成爲view,當加載的佈局的layout_width 和layout_height 不爲warp_content(因爲默認的便是warp_content)時(當然還有其他layout_xx屬性,這裏都是類似的)
inflate 時root爲null時:
因爲view沒有父佈局,所以view無法計算layout_xx屬(因爲layout_xx的意思是view在 父佈局中的位置尺寸信息,所以沒有父佈局,layout_xx屬性無法計算),所以此時的佈局屬性都爲默認(layout_width 和 layout_height 都爲warp_content,這樣設計也是很合理的,因爲雖然不能得知自身的大小,而且系統又必須需要一個尺寸去繪製,所以佈局會算出自身最小的尺寸爲多少,當佈局中沒有任何子視圖時,那麼它就會得到自身最小的尺寸爲0)
示例:
首先我們建議個activity的佈局文件,並在該佈局中添加我們要動態加載的view
activity佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rl_parent">
<Button
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:text="添加"
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
我們要加載的view的佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#00ff00">
<Button
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button" />
</LinearLayout>
上面我們設置view的layout_width和layout_height屬性都爲200dp
在代碼中加載view並將該view添加到我們的activity的佈局中
public class InlterAndAddViewDemoActivity extends BaseActivity {
@ViewInject(id = R.id.btn_add)
private Button mBtnAdd;
private LayoutInflater mInflater;
private ViewGroup mLayout;
@Override
protected int initLayout() {
return R.layout.activity_inlter_and_add_view_demo;
}
@Override
protected void initView() {
ViewUtils.inject(this);
mBtnAdd.setOnClickListener(this);
mInflater = LayoutInflater.from(this);
mLayout = (ViewGroup) findViewById(R.id.rl_parent);
}
@Override
protected void OnClick(View v) {
switch (v.getId()) {
case R.id.btn_add: {
addButton();
}
break;
}
}
private void addButton() {
View v = mInflater.inflate(R.layout.inlatebutton_layout, null, false);
mLayout.addView(v);
}
}
運行後如下圖:
可以看到我們設置的layout_width 和 layout_height並未生效,下面我們看一下view的LayoutParam
繼續查看addView(child,-1)
可以看到,如果LayoutParam爲空時,系統會爲view生成一個默認的layoutparam,我們在看一下generateDfaultLayoutparams();
這樣我們就明白了,當我們加載view時,root爲空,系統會爲view設置layout_width和layout_height設置爲warp_content,以及其他layout_xx設置默認值,所以我們在xml設置的layout_xx屬性無法生效。
當inflate中的root不爲null時 attachToRoot爲false:
我們修改上面的添加view的代碼
LinearLayout l = new LinearLayout(this);
View v = mInflater.inflate(R.layout.inlatebutton_layout, l, false);
Log.i(TAG,"LayoutParam===" + v.getLayoutParams());
mLayout.addView(v);
運行結果:
可以看到我們的view的layout_width和layout_height生效了,下面我們爲view多添加幾個layout_xx屬性看一下
inflate_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:orientation="vertical"
android:layout_margin="20dp"
android:layout_gravity="center_horizontal"
android:background="#00ff00">
<Button
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button" />
</LinearLayout>
我們添加了margin和gravity屬性,看下效果
可以看到和我們之前沒有添加時下效果是一樣的,爲什麼呢?之前我們已經得到結論,當一個view的LayoutParams爲空時,則系統爲他默認設置一個默認的LayutParam,而默認的layout_width和layout_height 都爲warp_content,所以當root沒有設置LayoutParam時,它的layout_width和layout_height都爲warp_content,那麼root將包裹view,所以也就不存在margin和gravity屬性的意義了。
所以我們需要給root手動的設置以個LayoutParam,而且如果我們需要view的其他layout_xx屬性生效,我們只要將attachToRoot設置爲true就行了(詳情參見郭神的文章)
本文爲本人學習研究記錄.