有的時候,咱們配置好的佈局文件,在加載完成添加到咱們的Activity中後發現,並無安裝咱們設置的屬性 java
來佈局,比爲咱們設置了android:layout_marginTop="100dip",可是運行程序後發現一點做用都沒有,類似的還有layout_height等以android:layout_開頭的屬性設置都沒有做用,這類問題以咱們使用Adapter的做爲數據源的時候做用居多,由於Adapter裏有一個方法是getView,這個返回的VIew是一個從XML佈局里加載的,通常以下: android
if(convertView==null){
convertView=LayoutInflater.from(mContext).inflate(R.layout.main, null);
}
return convertView;
問題偏偏出在咱們的LayoutInflater.from(mContext).inflate(R.layout.main, null);這句代碼上,在使用inflate的時候,若是第二個參數(View root)爲null,那麼將不會加載你的佈局文件裏的最頂層的那個佈局節點的佈局相關配置(就是以android:layout_開頭的屬性)..咱們能夠看下該方法的實現來講明一下,經過查找源代碼,inflate的實現都在這個public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) 方法裏定義。。其中一段:
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
}
能夠看到,當root爲null的時候是不會執行params = root.generateLayoutParams(attrs);這段代碼的,這段代碼就是把xml裏的佈局配置轉爲LayoutParams,換句說就是加載咱們配置的佈局屬性,以供佈局類(FrameLayout等)在onLayout的時候控制View的大小、位置、對齊等等。。以FrameLayout爲例,看下它的generateLayoutParams(attrs)方法。
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new FrameLayout.LayoutParams(getContext(), attrs);
}
很簡單,構造了一個FrameLayout.LayoutParams類,該類集成了MarginParams,增長了一個gravity對其的屬性配置。。。
在這裏,若是要自定義本身的VIewroup,而且該ViewGroup有一些自定義控制佈局的屬性設置,就能夠經過
集成View.MarginParams來擴展布局配置,而後重寫generateLayoutParams方法,這樣系統框架就會自動使用該佈局讀取咱們在xml中配置的佈局屬性來控制咱們的VIew的位置。。
基於以上分析,咱們在使用LayoutInflate的inflate方法的時候必定要保證root參數不能爲null,其實這個root就是父View的意思,就是說你把xml轉換爲一個VIew的時候,該VIew的Parent是root,若是你不想把該View添加到該root裏,那麼讓第三個參數 attachToRoot爲false,若是要添加則爲true.
說到這個問題了,其實還有一些佈局,他們的參數配置要知足必定的條件纔會起做用,好比FrameLayout裏的View,你要想它的leftMargin生效,必須指定它的layout_gravity爲left,同理right對應rightMargin.top和bottom也同樣。。在使用時注意便可,多看看源代碼。要否則就會莫名起名,不知道哪裏的問題。
ViewGroup的三條線
onMeasure 測量View的大小
onLayout 對View的佈局進行控制
draw繪製該View,drawChild繪製子VIew