學習完第一行代碼後,繼續學習Android群英傳,希望能堅持下去,好好學習完這本書,並及時做好相關筆記,鞏固相關知識; 一. View的介紹: 1`.我們先來看下view樹結構: 2.樹結構內容: a.viewparent是整棵樹的核心,它統一調度和分配所有的交互管理事件。 b.控制項分為viewgr ...
學習完第一行代碼後,繼續學習Android群英傳,希望能堅持下去,好好學習完這本書,並及時做好相關筆記,鞏固相關知識;
一. View的介紹:
1`.我們先來看下view樹結構:
2.樹結構內容:
a.viewparent是整棵樹的核心,它統一調度和分配所有的交互管理事件。
b.控制項分為viewgroup和view兩種控制項,viewgroup作為父控制項可以包含多個vie w控制項。
c.我們知道在使用控制項前都要通過findViewById的方法來實例化控制項,那麼在樹結構中,實際上表現為通過樹的深度優先遍歷來查找到對應的元素。
3.UI界面構架圖:
4.UI界面構架圖內容:
a.實際上每個activity都包含一個window對象,而window對象是通過PhoneWindow來實現的。
b.PhoneWindow又將一個DecorView設置為整個應用視窗的根View。(簡單的來說就是,我們所看到的整個手機屏幕內容就是整個的DecorView);
c.然後在我們手機應用中,一般含有兩個view,一個是標題欄,即TitleView,另一個就是呈現內容的view,即ContentView.(當然,我們也可以通過一些辦法隱藏,比如在setContentView()之前使用:
requestWindowFeature(Window.FEATURE_NO_TITLE)的方法即可。)
d.界面的顯示過程:當程式在onCreate()方法中調用setContentView方法後,ActivityManagerService會回調onResume方法,系統便會將整個DecorView添加到PhoneWindow中。
二. View的測量:
1.測量的模式有三種:
EXACTLY模式:指的是精確值模式,比如我們設置layout_width=30dp,那麼這種便屬於精確值模式。
AT_MOST模式:指的是最大值模式,比如我們使用的wrap_content便是屬於這種模式,允許隨著內容的變化而變化,只要不超過父控制項的所允許的最大尺寸即可。
UNSPECIFIED模式:這個是沒有限制的模式,想要多大就可以多大,一般是在自定義view中使用。
2.關於重寫onMeasure()方法:
a.為什麼要重寫onMeasure方法?
因為view類預設的onMeasure方法只支持EXACTLY模式,所以如果我們想要用指定wrap_content的大小的話,就必須要重寫該方法。
b.重寫onMeasure的過程:
(1)創建一個類繼承至view:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
我們會看到這樣的一個初始的onMeasure函數,然後我們來看下super.OnMeasure的方法:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
所以在這裡我們要重寫setMeasuredDimension這個函數:我們再下麵添加這樣一句話
setMeasuredDimension(measureSize(200,widthMeasureSpec),measureSize(200,heightMeasureSpec));
我們來看下這句話的含義,實際上我們自定義了一個measureSize的函數,然後分別傳入兩個參數,第一個為預設值,第二個實際值。然後我們來看下這個自定義函數是如何實現的:
private int measureSize(int defaultSize,int measureSpec){ int result=0;//定義result來作為返回值 int specMode=MeasureSpec.getMode(measureSpec);//獲取到測量的模式 int specSize=MeasureSpec.getSize(measureSpec);//獲取到測量值 if (specMode==MeasureSpec.EXACTLY){//如果為精確測量,返回測量值即可 result=specSize; }else{ result=defaultSize;//如果為其他兩種模式,設置為預設值 if (specMode==MeasureSpec.AT_MOST){//如果為最大值模式,我們要獲取到預設值和測量值中最小的值 result=Math.min(result,specSize); } } return result; }
最後我們在xml文件中引用這個自定義的view:
<main.view.com.view.viewTest android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ff0000" />