本系列文章循序漸進(jìn)的學(xué)習(xí)Android View的使用和核心源碼分析缩抡。
Android View (1) View的樹形結(jié)構(gòu)和坐標(biāo)計(jì)算
Android View (2) View的加載過程
Android View (3) View LayoutInflater 源碼分析
Android View (4) View的繪制過程
View的樹形結(jié)構(gòu)
- View 是Android UI 控件的基類,ViewGroup也是繼承自View澎蛛,Android中的控件分為兩部分宗兼,直接繼承自View的控件和繼承ViewGroup的布局(控件的集合)躏鱼,使整個(gè)Android控件形成的界面呈現(xiàn)出一個(gè)樹形結(jié)構(gòu)。每個(gè)父控件要負(fù)責(zé)繪制和測(cè)量下層控件殷绍,并進(jìn)行事件傳遞交互染苛。每棵樹的根都存在一個(gè)核心的ViewParent對(duì)象,負(fù)責(zé)對(duì)整個(gè)視圖進(jìn)行統(tǒng)一的調(diào)度和分配主到。ViewParent相當(dāng)于控件樹的心臟茶行。
-
在Android中贸呢,一個(gè)Activity的View結(jié)構(gòu)如圖所示:Activity的View結(jié)構(gòu).png
在每個(gè) Activity 創(chuàng)建時(shí),同時(shí)會(huì)創(chuàng)建一個(gè) Window (抽象類)拢军,Window 的具體通過 PhotoWindow 類實(shí)現(xiàn)楞陷,它也是唯一的 Window 實(shí)現(xiàn)類,PhotoWindow 又創(chuàng)建了一個(gè) DecorView(間接的繼承自View)作為整個(gè)Activity的根布局茉唉。DecorView 被分為兩部分:ActionBar 部分(一般開發(fā)過程中都會(huì)隱藏固蛾,采用 google 推薦的 ToolBar)和 id 為 content的FragmentLayout部分,我們 setContentView(@LayoutRes int layoutResID) 設(shè)置的Activity XML布局就是在FragmentLayout中(這部分的加載過程度陆,下篇專門展開)接下來看android中的坐標(biāo)系艾凯。
坐標(biāo)系的計(jì)算
android坐標(biāo)系分為兩類: 絕對(duì)坐標(biāo)系(相對(duì)于設(shè)備的屏幕)和相對(duì)坐標(biāo)系也稱視圖坐標(biāo)系(相對(duì)于父控件)。
-
絕對(duì)坐標(biāo)系 如圖所示:絕對(duì)坐標(biāo)系.png
在Android中懂傀,將屏幕的左上角的頂點(diǎn)作為Android坐標(biāo)系的原點(diǎn)趾诗,這個(gè)原點(diǎn)向右是X軸正方向,原點(diǎn)向下是Y軸正方向蹬蚁。在這里主要強(qiáng)調(diào)MotionEvent觸摸事件的getRawX()和getRawY():是獲取的絕對(duì)坐標(biāo)恃泪,還有絕對(duì)坐標(biāo)經(jīng)常需要計(jì)算的幾個(gè)方法,在執(zhí)行測(cè)量的系統(tǒng)方法是,需要在布局加載出來之后進(jìn)行 一般在onWindowFocusChanged(boolean hasFocus)方法中執(zhí)行 :
//獲取整個(gè)屏幕寬高:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
//獲取狀態(tài)欄高度
Rect rect= new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rectangle.top;
//應(yīng)用程序App區(qū)域?qū)捀叩瘸叽绔@取
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
//View布局區(qū)域?qū)捀叩瘸叽绔@取
Rect rect = new Rect();
getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
-
視圖坐標(biāo)系 如圖所示:視圖坐標(biāo)系.png
視圖坐標(biāo)系其實(shí)就是我們?cè)谧远x控件犀斋,繪制過程中參考的坐標(biāo)系贝乎,也就是View自身相對(duì)于父控件的距離,一般獲取坐標(biāo)的方法有:
//View提供的方法:
//獲取View自身頂邊到其父布局頂邊的距離
view.getTop()
//獲取View自身左邊到其父布局左邊的距離
view.getLeft()
//獲取View自身右邊到其父布局左邊的距離
view.getRight()
//獲取View自身底邊到其父布局頂邊的距離
view.getBottom()
//返回值為getLeft()+getTranslationX()叽粹,當(dāng)setTranslationX()時(shí)getLeft()不變览效,getX()變。
view.getX()
//返回值為getTop()+getTranslationY()虫几,當(dāng)setTranslationY()時(shí)getTop()不變锤灿,getY()變。
view.getY()
//MotionEvent提供的方法:
//獲取點(diǎn)擊事件距離控件左邊的距離辆脸,即視圖坐標(biāo)
getX()
//獲取點(diǎn)擊事件距離控件頂邊的距離但校,即視圖坐標(biāo)
getY()
//獲取點(diǎn)擊事件距離整個(gè)屏幕左邊距離,即絕對(duì)坐標(biāo)
getRawX()
//獲取點(diǎn)擊事件距離整個(gè)屏幕頂邊的的距離每强,即絕對(duì)坐標(biāo)
getRawY()
還有一些滑動(dòng)始腾、動(dòng)畫的方法會(huì)在動(dòng)畫、滑動(dòng)事件的專題進(jìn)行解釋空执。
參考:
- 源碼:http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/
- 扔物線 博客:http://hencoder.com/
- 簡(jiǎn)書:
http://www.reibang.com/p/f76a6f6f75aa setContentView 加載視圖機(jī)制
http://www.reibang.com/p/0819a858b53c setContentView 源碼分析
http://www.reibang.com/p/bb7977990baa android view繪制流程,源碼解讀
http://www.reibang.com/p/b272528165a2 android 自定義view - ColorFilter:https://github.com/chengdazhi/StyleImageView(自定義view的玩法)