Android進階之view坐標系全面詳解
前言
首先祝大家國慶節(jié)快樂,玩的開心;
一、Android坐標系詳解
說到Android坐標系其實就是一個三維坐標,Z軸向上,X軸向右,Y軸向下。這三維坐標的點處理就能構成Android豐富的界面或者動畫等效果;
1、Android屏幕一些值的獲取
①獲取屏幕區(qū)域的寬高等尺寸獲取
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int widthPixels = metrics.widthPixels;
- int heightPixels = metrics.heightPixels;
②應用程序App區(qū)域寬高等尺寸獲取
- Rect rect = new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
③獲取狀態(tài)欄高度
- Rect rect= new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
- int statusBarHeight = rectangle.top;
④View布局區(qū)域寬高等尺寸獲取
- Rect rect = new Rect();
- getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
2、Android View絕對相對坐標系
View的靜態(tài)坐標方法
- getLeft():返回View自身左邊到父布局左邊的距離;
- getTop():返回View自身頂邊到父布局頂邊的距離;
- getRight():返回View自身右邊到父布局左邊的距離;
- getBottom():返回View自身底邊到父布局頂邊的距離;
- getX():返回值為getLeft()+getTranslationX(),當setTranslationX()時getLeft()不變,getX()變;
- getY():返回值為getTop()+getTranslationY(),當setTranslationY()時getTop()不變,getY()變;
3、手指觸摸屏幕時MotionEvent提供的一些方法
- getX():當前觸摸事件距離當前View左邊的距離
- getY():當前觸摸事件距離當前View頂邊的距離
- getRawX():當前觸摸事件距離整個屏幕左邊的距離
- getRawY():當前觸摸事件距離整個屏幕頂邊的距離
4、View寬高方法
- getWidth()layout后有效,返回值是mRight-mLeft;
- getHeight()layout后有效,返回值是mBottom-mTop;
- getMeasuredWidth()返回measure過程得到的mMeasuredWidth值;
- getMeasuredHeight()返回measure過程得到的mMeasuredHeight值;
5、Android View滑動相關坐標系
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中內(nèi)容(不是整個View)滑動到相應的位置,參考坐標原點為ParentView左上角,x,y為正則向xy軸反方向移動,反之同理;
- scrollBy(int x, int y)|在scrollTo()的基礎上繼續(xù)滑動xy。
- setScrollX(int value)|實質為scrollTo(),只是只改變Y軸滑動。
- setScrollY(int value)|實質為scrollTo(),只是只改變X軸滑動。
- getScrollX()/getScrollY()|獲取當前滑動位置偏移量。
關于Android View的scrollBy()和scrollTo()參數(shù)傳遞正數(shù)卻向坐標系負方向移動的特性可能很多人都有疑惑,甚至是死記結論,這里我們簡單給出產(chǎn)生這種特性的真實原因—-源碼分析,如下:
- 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的該方法注釋里明確說明了調運他會觸發(fā)onScrollChanged()和invalidated()方法,那我們就將矛頭轉向invalidated()方法觸發(fā)的draw()過程,draw()過程中最終其實會觸發(fā)下面的invalidate()方法,如下:
- public void invalidate(int l, int t, int r, int b) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- //scroller時為何參數(shù)和坐標反向的真實原因
- invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
- }
核心就在這里
scrollTo()和scrollBy()方法特別注意:如果你給一個ViewGroup調用scrollTo()方法滾動的是ViewGroup里面的內(nèi)容,如果想滾動一個ViewGroup則再給他嵌套一個外層,滾動外層即可
總結
- view獲取自身坐標:getLeft(),getTop(),getRight(),getBottom()
- view獲取自身寬高:getHeight(),getWidth()
- motionEvent獲取坐標:getX(),getY(),getRawX(),getRawY()
- 然后是motionEvent的方法:
- getX():獲取點擊事件相對控件左邊的x軸坐標,即點擊事件距離控件左邊的距離
- getY():獲取點擊事件相對控件頂邊的y軸坐標,即點擊事件距離控件頂邊的距離
- getRawX():獲取點擊事件相對整個屏幕左邊的x軸坐標,即點擊事件距離整個屏幕左邊的距離
- getRawY():獲取點擊事件相對整個屏幕頂邊的y軸坐標,即點擊事件距離整個屏幕頂邊的距離