Android開發程序中,針對View視圖坐標系必要時獲取坐標,其重要性不言而喻,坐標系分為螢屏坐標系和View視圖坐標系,前者用于真實坐標,后者用于獲取相對坐標和寬高,
Android視圖坐標系
android中的坐標系有兩種:一種是Android坐標系,是相對螢屏原點來說的,也可以叫絕對坐標;另外一種是視圖坐標系,是根據當前view以及父布局來說的,
Android坐標系

以螢屏左上角原點為中心,x軸向右為正,y軸向下為正,
視圖坐標系

根據view自身相關屬性計算view所處坐標,
獲取View的距離和位置
下面介紹Android View類中用來獲取View的距離和位置資訊的一些API,這些API大都需要在Attach到Window之后才能獲取到預期的結果,所以不能放在構造方法,onCreate(),onMeasure(),onLayout()等方法中執行,一般都需要放到onWindowFocusChanged()里,或者放到某個異步事件中執行,
getWidth()/getHeight()
getHeight():獲取View自身高度;getWidth():獲取View自身寬度,
getTranslationX()/getTranslationY()/getTranslationZ()
TranslationX和TranslationY是從Android3.0引入的View的屬性,TranslationZ則是Android5.0引入的View的屬性,它們分別表示將View從其原始位置沿著X,Y,Z軸方向平移的距離,
getTop()/getBottom()/getLeft()/getRight()/getElevation()
通過如下方法可以獲得View到其父控制元件(ViewGroup)的距離:
- getTop():獲取View自身頂邊到其父布局頂邊的距離
- getLeft():獲取View自身左邊到其父布局左邊的距離
- getRight():獲取View自身右邊到其父布局左邊的距離
- getBottom():獲取View自身底邊到其父布局頂邊的距離
- getElevation():獲取View Z軸偏移量
getElevation()的結果則是之前在XML中通過android:elevation配置的值,或者是通過setElevation()設定的值,其中getElevation()只有在Android5.0及之后的系統中才可以使用,
getX()/getY()/getZ()
getX()/getY()/getZ()同樣是用來獲取一個view到parent view的距離,和getTop()/getLeft()/getElevation()不同是,getX()/getY()/getZ()會考慮TranslationX,TranslationY和TranslationZ的影響,可以簡單的將getTop()/getLeft()/getElevation()結果和getTranslationX()/getTranslationY()/getTranslationZ()結果相加,即可得到getX()/getY()/getZ()的結果,getX()和getY()只有在Android3.0及之后的系統才可以使用,getZ()只有在Android5.0及之后的系統中才可以使用,
getScrollX()/getScrollY()
getScrollX()/getScrollY()用來獲取一個view滑動的距離,一般來說,如果View是不可滑動的,例如TextView,Button等, getScrollX()/getScrollY()獲取到的始終是0,如果View是可以縱向滑動的,例如ListView,ScrollView等,getScrollX()獲取到的始終是0,getScrollY()獲取到的是Y軸滾動的距離,如果View是可以橫向滑動的,例如HorizontalScrollView,getScrollY()獲取到的始終是0,getScrollX()獲取到的是X軸滾動的距離,getScrollX()和getScrollY()的值始終大于等于0,
getDrawingRect()
getDrawingRect()用來獲取一個View的繪制區域,它本身沒有回傳值,需要傳入一個不為null的Rect物件作為輸出引數,一般來說,一個View的繪制區域就是從(0, 0)到(width, height)的區域,但如果View是可滑動的,則它的繪制區域還要加上滑動的距離,也就是從(scrollX, scrollY)到(width+scrollX, height+scrollY)的距離,
需要注意的是getDrawingRect()并沒有考慮setScaleX(),setScaleY()和setRotation()的影響,所以它回傳的區域大小并不一定會和View當前實際顯示的區域大小相同,
getLocationOnScreen()和getLocationInWindow()
getLocationOnScreen()和getLocationInWindow()回傳的都是view左上角的坐標,不同的getLocationOnScreen()得到的是相對于螢屏的坐標,也就是坐標原點在螢屏的左上角,而getLocationInWindow()得到的是相對于當前視窗的坐標,也就是坐標原點在視窗的左上角,
int[] screenLocation = new int [2];
int[] windowLocation = new int [2];
getLocationInWindow();
getLocationOnScreen(windowLocation)
getGlobalVisibleRect()和getLocalVisibleRect()
這兩個方法主要用于判斷一個 View 是在某個區域的可見性,區別:
- View.getGlobalVisibleRect(rect); //以螢屏 左上角 為參考系的
- View.getLocalVisibleRect(rect); //以目標 View 左上角 為參考系
判斷是否可見:
boolean localVisibleRect = target.getLocalVisibleRect(rect);
回傳值:
- true : View 全部或者部分 可見
- false : View 全部不可見
點擊事件MotionEvent提供的坐標方法
我們看視圖坐標系圖示中那個深藍色的點,假設就是我們觸摸的點,我們知道無論是View還是ViewGroup,最終的點擊事件都會由onTouchEvent(MotionEventevent)方法來處理,MotionEvent也提供了各種獲取焦點坐標的方法:
- getX():獲取點擊事件距離控制元件左邊的距離,即視圖坐標
- getY():獲取點擊事件距離控制元件頂邊的距離,即視圖坐標
- getRawX():獲取點擊事件距離整個螢屏左邊距離,即絕對坐標
- getRawY():獲取點擊事件距離整個螢屏頂邊的的距離,即絕對坐標
幾個問題
- View 的 getY(), getTranslationY() 和 getTop() 之間的聯系;
- View 的 scrollTo() 和 scrollBy();
View的getY(),getTranslationY()和getTop()之間的聯系:
getY() = getTranslationY()+ getTop();
scrollTo()和scrollBy()從字面意思我們可以知道scrollTo()是滑動到哪里的意思 ,scrollBy()是相對當前的位置滑動了多少,
需注意:scrollTo和scrollBy函式的引數和坐標系是“相反的”,比如 scrollTo(-100,0),View 的內容是向X軸正方向移動的,
view坐標獲取時機
一般來說,我們要獲取View的坐標和高度等,都必須等到View繪制完畢以后才能獲取的到,在Activity的onCreate()方法里面是獲取不到的,必須等到View繪制完畢以后才能獲取地到View的回應的坐標,一般來說,主要有以下兩種方法,
第一種方法,onWindowFocusChanged()方法里面進行呼叫
因為onWindowFocusChanged可能會呼叫多次,所以我們可以用一個唯一標識來控制獲取坐標呼叫一次即可,
第二種方法,在視圖樹繪制完成的時候進行測量
利用view.getViewTreeObserver().addOnGlobalLayoutListener監聽view是否整個繪制完畢,然后進行獲取坐標,
參考
- https://blog.csdn.net/itachi85/article/details/50708391
- https://juejin.im/entry/5880209c2f301e006968a342
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/266694.html
標籤:其他
