1-1View坐標系
1-2父View移出屏幕后子View的getLeft()值
1.View靜態坐標
View坐標 | 參數含義 |
---|---|
Left = getLeft(); | View自身左側到父View左側的距離 |
Top = getTop(); | View自身頂部到父View頂部的距離 |
Right = getRight(); | View自身右側到父View左側的距離 |
Bottom = getBottom(); | View自身底部到父View頂部的距離 |
getTranslationX() | View左上角相對父View的X軸偏移量 |
getTranslationY() | View左上角相對父View的Y軸偏移量 |
getX() | 值為getLeft()+getTranslationX(),當setTranslationX()時getLeft()不變,getX()變。 |
getY() | 值為getTop()+getTranslationY(),當setTranslationY()時getTop()不變,getY()變。 |
MotionEvent觸摸事件坐標、
MotionEvent坐標方法 | 參數含義 |
---|---|
getX() | 當前觸摸點距離當前View自身左邊的距離 |
getY() | 當前觸摸點距離當前View自身頂部的距離 |
getRawX() | 當前觸摸點距離屏幕左邊的距離(Android絕對坐標系) |
getRawY() | 當前觸摸點距離屏幕頂部的距離(Android絕對坐標系) |
2.View中的滑動坐標系
Paste_Image.png
View滑動坐標 | 參數含義 |
---|---|
offsetLeftAndRight(int offset) | 水平方向挪動View,offset為正則x軸正向移動,移動的是整個View,getLeft()會變的,自定義View很有用。 |
offsetTopAndBottom(int offset) | 垂直方向挪動View,offset為正則y軸正向移動,移動的是整個View,getTop()會變的,自定義View很有用。 |
scrollTo(int x, int y) | 將View中內容(不是整個View)滑動到相應的位置,參考坐標原點為ParentView左上角,x,y為正則向xy軸反方向移動,反之同理。 |
scrollBy(int x, int y) | 在scrollTo()的基礎上繼續滑動xy。 |
setScrollX(int value) | 實質為scrollTo(),只是改變X軸滑動。 |
setScrollY(int value) | 實質為scrollTo(),只是改變Y軸滑動。 |
getScrollX()/getScrollY() | 獲取當前滑動位置偏移量。分別對應著mScrollX、mScrollY。mScrollX的值總是等于View左邊緣和View內容左邊緣在水平方向的距離,mScrollY的值總是等于View的上邊緣和View內容上邊緣在豎直方向的距離。View邊緣指View的位置,有四個頂點組成,Left、Top、Right、Bottom。所以該值的參考坐標系是父View的左上角。 |
mScrollX = getLeft()-mContentDistanceX;
mScrollY = getTop()-mContentDistanceY;
(mContentDistanceX和mContentDistanceY分別是View的內容在X軸、Y軸滑動的距離)
mScrollX和mScrollY的單位為像素,并且當View左邊緣(getLeft())在View內容左邊緣的右邊時,mScrollX為正值,反之為負值;當View上邊緣(getTop())在View內容上邊緣的下邊時,mScrollY為正值,反之為負值。
同理,調用View的scrollBy()和scrollTo()方法時參數傳遞正數,卻想坐標系負方向移動。
源碼分析:
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
View的該方法注釋里明確說明了調運他會觸發onScrollChanged()和invalidated()方法,那我們就將矛頭轉向invalidated()方法觸發的draw()過程,draw()過程中最終其實會觸發下面的invalidate()方法,如下:
public void invalidate(int l, int t, int r, int b) {
final int scrollX = mScrollX;
final int scrollY = mScrollY; //scroller時為何參數和坐標反向的真實原因
invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
}
invalidate()的四個參數分別是View的Left、Top、Right和Bottom,代碼中mScrollX和mScrollY。l-scrollX,當scrollX為負時,l-scrollx > l,此時View內容的左邊緣在view左邊緣的右側,同理說明scrollX、scrollY傳負值時,View的內容往坐標系正值方向移動。