Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android坐標

android坐標

編輯:關於Android編程

說來說去都不如 畫圖示意 簡單易懂啊!!!真是的! 來吧~~先上張圖~~!

\

 

(一)首先明確一下Android中的坐標系統

屏幕的左上角是坐標系統原點(0,0) 原點向右延伸是X軸正方向,原點向下延伸是Y軸正方向 (二)關於Scroll: 屏幕顯示的內容很多時,會有超出一屏的情況,於是就產生了Scroll的概念。 在View類中有個方法: getScrollY()英文原文描述是: Return the scrolled top position of this view. This is the top edge of the displayed partof your view.... 其實理解起來仍然就是:就是這個view相對於“坐標系統原點”(見上圖)在Y軸上的偏移量.(getScrollX同理) 【哇哈,有了圖就是好說明啊~ 省了多少語言描述啊,而且還不一定能說清楚~】   getScrollY()就是當前視圖相對於屏幕原點在Y軸上的偏移量.

(三)MotionEvent類中getRowX()和getX()的區別:

event.getRowX():觸摸點相對於屏幕原點的x坐標
event.getX():觸摸點相對於其所在組件原點的x坐標

於是乎: view.getScrollY() + event.getY() 就得到了view中的觸摸點在Y軸上的偏移量

 

(四)TextView類中

有個 getLayout()方法:the Layout that is currently being used to display the text. This

can be null if the text or width has recently changes.

其返回類型是Layout ,也就是返回textView的布局。

然後重要的是通過這個 layout調用一個方法:

getLineForVertical(int verticalPointPosition)//得到某點在垂直方向上的行數值

於是綜上所述,在實際的觸摸事件中可以這樣使用:

Layout layout=textView.getLayout();

int line = layout.getLineForVertical(textView.getScrollY() + (int) event.getY());

//得到觸摸點在textView中垂直方向上的行數值。參數是觸摸點在Y軸上的偏移量

接下來繼續介紹一個方法,要用到上邊的 layout 和 line:

layout.getOffsetForHorizontal( line ,(int) event.getX() );

//得到觸摸點在某一行水平方向上的偏移量。

參數分別是: 該行行數值 和 觸摸點在該行X軸上的偏移量。

此方法得到的該值會根據該行上的文字的多少而變化,並不是橫向上的像素大小;


 

 

\

 

 

整個坐標系是以手機屏幕左上角為原點(0,0),如果在屏幕沒有滑動之前,這一理解肯定是ok的,但在滑屏之後,就會產生很多歧義和混淆,原因在於使用過程當中,很多方法的參數並非是參照屏幕,而是相對於父視圖,對這整個過程和後面自定義控件的坐標變化帶來的各個參數變化來說理解起來就並不那麼適合了,最開始給人的感覺是越來越不清楚這個坐標該怎麼設置,好像坐標系總在發生變化,後來才慢慢在思維當中構建起視圖與視圖容器以及屏幕之間的關系。

android.view.View.layout(int l, int t, int r, int b) layout的過程就是確定View在屏幕上顯示的具體位置,在代碼中就是設置其成員變量mLeft,mTop,mRight,mBottom的值,這幾個值構成的矩形區域就是該View顯示的位置,不過這裡的具體位置都是相對與父視圖的位置。mLeft代表當前view.layout的這個view的左邊緣離它的父視圖左邊緣的距離,拿上面“子視圖2.layout(int l, int t, int r, int b)”來說,它的父視圖便是子視圖1,2,3合起來形成的整個大矩形,那麼這裡將父視圖的左上角定為(0,0),那麼可以確定mLeft為一個子視圖寬度320,以此類推,mTop指當前view的上邊緣離父視圖上邊緣的距離。而以此為界,mRight所指的是當前view的右邊緣離父視圖左邊緣的距離,一眼可以看出值為640(mLeft+自己的寬度),mBottom也是指當前view的下邊緣離父視圖的上邊緣的距離。至於為何如此,大概是因為坐標系的緣故,坐標中的任何點都必須以(0,0)為起點,XY軸為衡量。

視圖左側位置view.getLeft()
視圖右側位置 view.getRight()

視圖頂部位置 view.getTop();
視圖底部位置 view.getBottom();
這四個方法所獲取到的各個左上右下的值與layout的四個參數代表的是一樣的,都是相對父視圖的左邊緣與上邊緣。

視圖寬度 view.getWidth();
視圖高度 view.getHeight();
這兩個方法獲取的是該view的高和寬,僅僅在滑動的情況下,或者說該view的大小如果不發生變化,它的值是不會變的。
getMeasuredWidth();
getMeasuredHeight();
說到這裡就不得不提getWidth()、getHeight()和getMeasuredWidth()、getMeasuredHeight()這兩對函數之間的區別,getMeasuredWidth()、getMeasuredHeight()返回的是measure過程得到的mMeasuredWidth和mMeasuredHeight的值,而getWidth()和getHeight()返回的是mRight - mLeft和mBottom - mTop的值。一般情況下layout過程會參考measure過程中計算得到的mMeasuredWidth和mMeasuredHeight來安排子視圖在父視圖中顯示的位置,但這不是必須的,measure過程得到的結果可能完全沒有實際用處,特別是對於一些自定義的ViewGroup,其子視圖的個數、位置和大小都是固定的,這時候我們可以忽略整個measure過程,只在layout函數中傳入的4個參數來安排每個子視圖的具體位置。

view.getX();
view.getY();
getX和getY獲取到的值為相對於父視圖而言的兩個左邊緣和上邊緣的距離。

view.getLocationOnScreen(location);該方法可以獲取到當前view與屏幕的關系,location(0)代表X值,表示該view的左邊緣與屏幕的左邊緣之間的距離。可以想象,當滑屏產生,view開始移動該值肯定會改變的。location(1)代表Y值,表示該view的上邊緣與屏幕的上邊緣之間的距離,該距離肯定是包含標題欄的高度的。
getLocationInWindow();

ps:View.getLocationInWindow()和 View.getLocationOnScreen()在window占據全部screen時,返回值相同,不同的典型情況是在Dialog中時。當Dialog出現在屏幕中間時,View.getLocationOnScreen()取得的值要比View.getLocationInWindow()取得的值要大。

VelocityTracker.getXVelocity() 指滑動速度包括速率和方向兩個方面,往左滑動小於0,值為負;往右滑動大於0,值為正。




view.scrollTo(x,y)將整個父視圖的左上角定為(0,0),再移動這個屏幕的左上角到父視圖的點(x,y)處,注意此處的x和y是根據父視圖的坐標系來定的。
view.scrollBy(x,y)x代表橫向移動的距離,y代表縱向移動的距離

view.getScrollX
view.getScrollY
將整個父視圖的左上角定為(0,0),那麼子view.getScrollX會獲取到屏幕左邊緣減去父視圖的左邊緣為0的距離,特別當滑屏時,父視圖會被迫隱藏一部分,因為屏幕的大小是固定的。getScrollY以此類推。

event.getX()
event.getY()
相對父視圖左上角(0,0)觸摸點的坐標值。

Scroller.getCurrY()
Scroller.getCurrX()
該方法拿橫軸來說,代表屏幕的左邊緣離父視圖的左邊緣的距離。

Scroller.startScroll(int startX, int startY, int dx, int dy)
四個參數分別表示起點的坐標和滑動的向量,即從(startX,startY)開始滑動,橫向滑動dx的距離,縱向滑動dy的距離(正值向左滑,負值向右滑),而這裡的startX,startY又是參照的父視圖左上角為原點坐標的坐標系,滑屏時經常使用getScrollX()和getScrollY()來代表屏幕左邊緣和上邊緣處於父視圖坐標系的具體位置

TranslateAnimation()



以上是在做滑屏控件經常用到的方法,一方面需要了解layout和measure的基本流程,更重要一方面,當你想要實現某一個效果的時候,比如slidingmenu那樣的控件,查看源碼我們可以知道它是繼承的ViewGroup,該怎樣入手去做呢。

首先,需要了解它的父視圖是什麼,slidingmenu為例,打開程序,第一眼,是一個很普通的視圖頁面,當向右滑動手指,這個視圖頁面開始向右邊移動,而從左邊會慢慢移出來另一部分視圖,看上去像是抽出來的或者是隱藏的,事實上拋開陰影效果來講,想象手機屏幕的左邊有一部分我們看不到的視圖,它就是這個被抽出來的menu視圖了。概括來說,一個主view,一個menu其實是並排於一個大視圖上面的。
找到了父視圖,接下來就好辦了,認定這個父視圖的寬度就是主view的寬度和menu的寬度之和(暫不考慮padding之類),高度就是屏幕的高度,那麼在思維當中這個二維平面就產生了,將它想成一張紙,然後對准主view將這張紙貼到手機屏幕上,左右滑動,會看到其實slidingmenu也就是這麼個效果。

然後,實現的思路會清晰很多。定義這個父視圖為myview繼承viewgroup,原因在於盡管主view和menu並排在一個大view下,但畢竟兩者的內容不同,後面需要放進不同的控件處理不同的事件,這個父視圖內包含著兩個view,到時候處理起來會方便很多,setcontentview為這個父視圖,那麼打開程序的第一眼就會看到它。再定義這兩個view設置好兩個內容布局,並將它們addview添加到myview當中。外部工作基本就完成了,可以呈現父視圖,並且父視圖內有兩個子view。

接下來,需要去完善一些細節,父視圖內的子view該如何放置,這是關乎成敗的一環,也就是如何將這張紙貼到我們希望的位置,這時就是onlayout的處理了,處理好屏幕,父視圖子view之間的位置關系,通過各自的layout參數設置來擺放妥當各個view,比如開始的時候menu是隱藏的,這個就是通過位置的擺放設置的,然後它是從左邊滑出來的,說明它處於父視圖的左邊位置,而主view處於相對右邊的位置,而屏幕剛好也處於父視圖右邊的位置,恰好能看到主view的全貌,在腦海裡如果能有清晰的畫面出現,實現起來就會輕松很多。當實現了這個擺放,就可以理解menudrawer裡面上下左右都可以滑出menu的結構了。

最後,便是滑動效果,請相信這樣的控件裡面,任何處理肯定都會和view位置的擺放扯上關系,滑動方向,滑動距離等等都涉及到坐標的處理。這也是為何上面列出那些常用的獲取view坐標的方法。

總結下來,構建類似這樣的控件,也就這三點,明確父子視圖和屏幕的關系,通過坐標和位置參數設置它們的關系,處理這些關系發生變化的情況。


當然,事實上slidingmenu遠遠沒這麼簡單,其中為了方便後續開發,它內置了很多接口和處理,大多數都是位置坐標和事件監聽相關聯,而萬變不離其宗的是,它也肯定有這三個方面的構建,理解了這些基本的東西,嘗試做一些自己想象的效果,對自定義的理解來說,進步會非常大。  

 

 

\

 

資料來自互聯網

 

Android~獲取view在屏幕中的位置

 

getLocalVisibleRect, 返回一個填充的Rect對象, 感覺是這個View的Rect大小,left,top取到的都是0

getGlobalVisibleRect, 獲取全局坐標系的一個視圖區域, 返回一個填充的Rect對象;該Rect是基於總整個屏幕的

getLocationOnScreen,計算該視圖在全局坐標系中的x,y值,(注意這個值是要從屏幕頂端算起,也就是索包括了通知欄的高度)//獲取在當前屏幕內的絕對坐標

getLocationInWindow,計算該視圖在它所在的widnow的坐標x,y值,//獲取在整個窗口內的絕對坐標 (不是很理解= =、)

getLeft,getTop,getBottom,getRight, 這一組是獲取相對在它父親裡的坐標

**注**:如果在Activity的OnCreate()事件輸出那些參數,是全為0,要等UI控件都加載完了才能獲取到這些

example:

int[] location = new int[2];
v.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved