Android LayoutInflater原理分析,帶你一步步深刻了解View(一) 郭霖學習摘要

public class MainActivity extends Activity {
    //-----------------------UI----------------
    private RelativeLayout mMainLayout;
    private LinearLayout mBtnContainerLayout;
    //--------------------初始化----------------
    private int width;
    private int height;
    private int btnWidth;
    private int btnHeight;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMainLayout = (RelativeLayout)findViewById(R.id.layout_main);
        Log.d("TAG", "the parent layout is :" + mMainLayout.getParent());
        
        //LayoutInflater 動態載入button
        LayoutInflater inflater = LayoutInflater.from(this);
        View button  = inflater.inflate(R.layout.layout_button,null);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(600,300);
        button.setLayoutParams(params);
        mMainLayout.addView(button);     
    }
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">
   
</RelativeLayout>

inflate()方法還有個接收三個參數的方法重載,結構以下:html

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片java

  1. inflate(int resource, ViewGroup root, boolean attachToRoot)  android

那麼這第三個參數attachToRoot又是什麼意思呢?其實若是你仔細去閱讀上面的源碼應該能夠本身分析出答案,這裏我先將結論說一下吧,感興趣的朋友能夠再閱讀一下源碼,校驗個人結論是否正確。ide

1. 若是root爲null,attachToRoot將失去做用,設置任何值都沒有意義。佈局

2. 若是root不爲null,attachToRoot設爲true,則會在加載的佈局文件的最外層再嵌套一層root佈局。this

3. 若是root不爲null,attachToRoot設爲false,則root參數失去做用。spa

4. 在不設置attachToRoot參數的狀況下,若是root不爲null,attachToRoot參數默認爲true。.net

好了,如今對LayoutInflater的工做原理和流程也搞清楚了,你該知足了吧。額。。。。還嫌這個例子中的按鈕看起來有點小,想要調大一些?那簡單的呀,修改layout_button.xml中的代碼,以下所示:code

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片orm

  1. <Button xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="300dp"  
        android:layout_height="80dp"  
        android:text="Button" >  
      
    </Button>

這裏咱們將按鈕的寬度改爲300dp,高度改爲80dp,這樣夠大了吧?如今從新運行一下程序來觀察效果。咦?怎麼按鈕仍是原來的大小,沒有任何變化!是否是按鈕仍然不夠大,再改大一點呢?仍是沒有用!

其實這裏無論你將Button的layout_width和layout_height的值修改爲多少,都不會有任何效果的,由於這兩個值如今已經徹底失去了做用。平時咱們常常使用layout_width和layout_height來設置View的大小,而且一直都能正常工做,就好像這兩個屬性確實是用於設置View的大小的。而實際上則否則,它們實際上是用於設置View在佈局中的大小的,也就是說,首先View必須存在於一個佈局中,以後若是將layout_width設置成match_parent表示讓View的寬度填充滿布局,若是設置成wrap_content表示讓View的寬度恰好能夠包含其內容,若是設置成具體的數值則View的寬度會變成相應的數值。這也是爲何這兩個屬性叫做layout_width和layout_height,而不是width和height。

再來看一下咱們的layout_button.xml吧,很明顯Button這個控件目前不存在於任何佈局當中,因此layout_width和layout_height這兩個屬性理所固然沒有任何做用。那麼怎樣修改才能讓按鈕的大小改變呢?解決方法其實有不少種,最簡單的方式就是在Button的外面再嵌套一層佈局,以下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="300dp"
        android:layout_height="90dp"
        android:text="button" />
</LinearLayout>

能夠看到,這裏咱們又加入了一個LinearLayout,此時的Button存在與LinearLayout之中,layout_width和layout_height屬性也就有做用了。固然,處於最外層的LinearLayout,它的layout_width和layout_height則會失去做用。如今從新運行一下程序,結果以下圖所示:

                      

OK!按鈕的終於能夠變大了,這下總算是知足你們的要求了吧。

看到這裏,也許有些朋友心中會有一個巨大的疑惑。不對呀!平時在Activity中指定佈局文件的時候,最外層的那個佈局是能夠指定大小的呀,layout_width和layout_height都是有做用的。確實這主要是由於,在setContentView()方法中,Android會自動在佈局文件的最外層再嵌套一個FrameLayout,因此layout_width和layout_height屬性纔會有效果。那麼咱們來證明一下吧,修改MainActivity中的代碼,如頂部MainActivity代碼中的所示: 

Log.d("TAG", "the parent layout is :" + mMainLayout.getParent());


能夠看到,這裏經過findViewById()方法,拿到了activity_main佈局中最外層的LinearLayout對象,而後調用它的getParent()方法獲取它的父佈局,再經過Log打印出來。如今從新運行一下程序,結果以下圖所示:

 

很是正確!LinearLayout的父佈局確實是一個FrameLayout,而這個FrameLayout就是由系統自動幫咱們添加上的。

說到這裏,雖然setContentView()方法你們都會用,但實際上Android界面顯示的原理要比咱們所看到的東西複雜得多。任何一個Activity中顯示的界面其實主要都由兩部分組成,標題欄和內容佈局。標題欄就是在不少界面頂部顯示的那部份內容,好比剛剛咱們的那個例子當中就有標題欄,能夠在代碼中控制讓它是否顯示。而內容佈局就是一個FrameLayout,這個佈局的id叫做content,咱們調用setContentView()方法時所傳入的佈局其實就是放到這個FrameLayout中的,這也是爲何這個方法名叫做setContentView(),而不是叫setView()。

最後再附上一張Activity窗口的組成圖吧,以便於你們更加直觀地理解:

            

相關文章
相關標籤/搜索