AndroidUI的繪制流程

前言

前些天研究自定義控件特意研究了下UI的繪制流程

1.首先說下Activity加載后的顯示的View圖

2.然后我們從setContentView(R.layout.activity_main)入手,調用了Activity中的

public void setContentView(@LayoutRes int layoutResID) {

getWindow().setContentView(layoutResID);//1

initWindowDecorActionBar();

}

3.getWindow()拿到的是Window的實現類PhoneWindow

4,然后我們看PhoneWindow中的源碼的setContentView?

--------------------------------------------------------------------------------------

public void setContentView(int layoutResID) {

// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window

// decor, when theme attributes and the like are crystalized. Do not check the feature

// before this happens.

if (mContentParent == null) {

installDecor();//在這里創建了一個DecorView(繼承自FrameLayout)2

}

……

mLayoutInflater.inflate(layoutResID, mContentParent);//初始化我們自己的布局 ?6

}

------------------------------------------------------------------------------

//decorView的具體創建過程

private void installDecor() {

if (mDecor == null) {

mDecor = generateDecor();//生成一個DecorView 3

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

mDecor.setIsRootNamespace(true);

if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);

}

}

if (mContentParent == null) {

mContentParent = generateLayout(mDecor);//得到布局文件 4

}

----------------------------------------------------------------------------------------

protected ViewGroup generateLayout(DecorView decor) {//進行加載布局得到decorview中包含title和我們contentview的布局 ?5

View in = mLayoutInflater.inflate(layoutResource, null);

decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

mContentRoot = (ViewGroup) in;

}

----------------------------------------------------------------------------------

由此我們可以看出Activity加載View的流程是getWindow().setContentView(layoutResID)-->

installDecor()-->generateDecor()生成一個DecorView對象-->generateLayout(mDecor)得到DecorView加載的包括title和我們自己寫的布局的也就是rootview-->generateLayout(DecorView decor)得到rootView-->mLayoutInflater.inflate(layoutResID, mContentParent)加載我們自己的布局


View的繪制

1.View的繪制執行measure,layout,draw三個執行流程

View類中

? ? ? ? ? ? measure:測量自己多大,如果是ViewGroup的話會同時測量子控件

? ? ? ? ? ?layout:擺放子控件的位置

? ? ? ? ? ?draw:繪制

從View.java類的源碼中看到:

1.view的requestLayout()方法開始,遞歸不斷的往上找父容器,最終找到DecorView

2.執行DecorView的ViewRootImp類中的performTransversal()方法

3.performTranversal(){

// Ask host how big it wants to be

performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

performLayout(lp, desiredWindowWidth, desiredWindowHeight);

performDraw();

}

然后執行相應的measure,layout.draw方法,當是Viewgroup會調用相應的view的measure,layout,draw,當是View的時候調用measure,layout,draw然后執行想用onmeasure,onlayout,ondraw來進行相應的繪制

再說一下View的measure的測量規格MeasureSpec

1.mode

? ? ? ? ? ? ? 1)EXACTLY:精確的,例如我們寫的一個確定值50dp

? ? ? ? ? ? ? 2)AT_MOST:根據父容器當前的大小,結合你指定的尺寸參考值來考慮你應該是多大尺寸,需要計算(Match_parent,wrap_content就是屬于這種)

? ? ? ? ? ? ? 3)UPSPECIFIED:最多的意思。根據當前的情況,結合你制定的尺寸參考值來考慮,在不超過父容器給你限定的只存的前提下,來測量你的一個恰好的內容尺寸。用的比較少,一般見于ScrollView,ListView(大小不確定,同時大小還是變的。會通過多次測量才能真正決定好寬高。)

2.value:寬高的值

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容