關於LayoutInflater的inflate方法和LayoutParam分析(二)

其實通過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

測試

這裏我們看到LayoutParam爲空,所以我們看一下當LayoutParam爲空時addView是怎麼處理的:

圖片addView

繼續查看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就行了(詳情參見郭神的文章)

本文爲本人學習研究記錄.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章