有的時候,我們配置好的布局文件,在加載完成添加到我們的Activity中后發現,並沒有安裝我們設置的屬性
來布局,比為我們設置了android:layout_marginTop="100dip",但是運行程序后發現一點作用都沒有,相似的還有layout_height等以android:layout_開頭的屬性設置都沒有作用,這類問題以我們使用Adapter的作為數據源的時候作用居多,因為Adapter里有一個方法是getView,這個返回的VIew是一個從XML布局里加載的,一般如下:
- 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);
- }
- }
- 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