Android自定義View學習(一):實心圓

1. View的基礎知識

1. 什麼是View

View是Android中所有控件的基類,View的本身可以是單個空間,也可以是多個控件組成的一組控件,即ViewGroup,ViewGroup繼承自View,其內部可以有子View,這樣就形成了View樹的結構。


2. View的位置參數

View的位置主要由它的四個頂點來決定,即它的四個屬性:top、left、right、bottom,可用來分別表示View左上角的座標點( top,left) 以及右下角的座標點( right,bottom) 。

View的位置參數
這四個參數可以由以下方式獲取:

int left = getLeft();
int right = getRight();
int top = getTop();
int bottom = getBottom();

根據這張圖,我們可以得到一些簡單的換算:

int width = right - left;    //寬度
int height = bottom - top;   //高度

Android3.0後,View增加了x、y、translationX和translationY這幾個參數。其中x和y是View顯示時左上角相對於父容器的座標:

int x = getX();
int y= getY();

getX( ) 和 getLeft( ) 得到的值的區別是:

  • left:View的左邊相對於父View左邊的距離。這個值不會隨着View的屬性(transitionX和X)改變。
  • View在layout的時候,會調用setFrame函數來改變left的值。客戶端可以直接調用setLeft( )來改變left值。
  • left值改變後,View的大小也會改變。因爲View的大小是right - left;
  • x: View實際顯示位置的左邊相對於父View左邊的距離。它的值是 translationX + left;
  • tanslationX:View 相對於left的位移。屬性動畫改變的是x和translationX的值,沒有改變left的值。

他們之間的換算關係如下:

x = left + translationX;
y = top + translationY;

來個更詳細的圖:

View的完整位置參數

上圖很好的說明了每個方法獲得的座標值或者距離代表的意義,圖中有三個黑色的框框,最外層是手機屏幕,中間層是ViewGroup,最內層是ViewGroup中的View。

其實上圖中標註的方法可以分爲兩類,一類是View提供的方法,一類是MotionEvent提供的方法:

1.View提供的獲取的座標以及距離的方法:

getX();             //獲取到的是view顯示位置的左邊到其父佈局左邊的距離
getY();             //獲取到的是view顯示位置的頂邊到其父佈局頂邊的距離
getTop();           //獲取到的是view自身的頂邊到其父佈局頂邊的距離
getLeft();          //獲取到的是view自身的左邊到其父佈局左邊的距離
getRight();         //獲取到的是view自身的右邊到其父佈局左邊的距離
getBottm();         //獲取到的是view自身的底邊到其父佈局頂邊的距離

2.MotionEvent提供的方法:

getX();             //獲取點擊事件距離控件左邊的距離,即視圖座標
getY();             //獲取點擊事件距離控件頂邊的距離,即視圖座標
getRawX();          //獲取到的是點擊事件距離整個屏幕左邊的距離,即絕對座標
getRawY();          //獲取到的是點擊事件距離整個屏幕頂邊的距離,即絕對座標
getScrollY();       //獲取 視圖座標原點 到 視圖 滾出屏幕 的距離
getScrollX();       //類似 同上

3. View的工作原理

ViewRoot的實現是 ViewRootImpl 類,是連接WindowManager和DecorView的紐帶,View的三大流程( mearsure、layout、draw) 均是通過ViewRoot來完成。當Activity對象被創建完畢後,會將DecorView添加到Window中,同時創建 ViewRootImpl 對象,並將ViewRootImpl 對象和DecorView建立連接,源碼如下:

root = new ViewRootImpl(view.getContext(),display);
root.setView(view,wparams, panelParentView);

看一張圖

View的繪製流程

View的繪製流程是從ViewRoot的performTraversals()方法開始的,然後是:
- measure( ):用來測量View的寬高 ;
- layout( ):來確定View在父容器中的位置 ;
- draw( ):負責將View繪製在屏幕上。

performTraversals()會依次調用 performMeasure( ) 、 performLayout( ) 和performDraw( ) 三個方法,這三個方法分別完成頂級View的measure( )、layout( )和draw( )這三大流程。其中 performMeasure( ) 中會調用 measure( ) 方法,在 measure( ) 方法中又會調用 onMeasure( ) 方法,在 onMeasure ( )方法中則會對所有子元素進行measure過程,這樣就完成了一次measure過程;子元素會重複父容器的measure過程,如此反覆完成了整個View數的遍歷。另外兩個過程同理。

  • Measure完成後, 可以通過getMeasuredWidth( )、getMeasureHeight( )
    方法來獲取View測量後的寬/高。特殊情況下,測量的寬高不等於最終的寬高,詳見後面。

  • Layout過程決定了View的四個頂點的座標和實際View的寬高,完成後可通過 getTop( ) 、 getBottom( ) 、 getLeft( ) 和 getRight( ) 拿到View的四個定點座標。


4. View的MeasureSpec

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章