一、Android坐标系详解
说到Android坐标系其实就是一个三维坐标,Z轴向上,X轴向右,Y轴向下。这三维坐标的点处理就能构成Android丰富的界面或者动画等效果;
1、Android屏幕一些值的获取
①获取屏幕区域的宽高等尺寸获取
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int widthPixels = metrics.widthPixels;
- int heightPixels = metrics.heightPixels;
②应用程序App区域宽高等尺寸获取
- Rect rect = new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
③获取状态栏高度
- Rect rect= new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
- int statusBarHeight = rectangle.top;
④View布局区域宽高等尺寸获取
- Rect rect = new Rect();
- getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
2、Android View绝对相对坐标系
View的静态坐标方法
- 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中内容(不是整个View)滑动到相应的位置,参考坐标原点为ParentView左上角,x,y为正则向xy轴反方向移动,反之同理;
- scrollBy(int x, int y)|在scrollTo()的基础上继续滑动xy。
- setScrollX(int value)|实质为scrollTo(),只是只改变Y轴滑动。
- setScrollY(int value)|实质为scrollTo(),只是只改变X轴滑动。
- getScrollX()/getScrollY()|获取当前滑动位置偏移量。
关于Android 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);
- }
核心就在这里
scrollTo()和scrollBy()方法特别注意:如果你给一个ViewGroup调用scrollTo()方法滚动的是ViewGroup里面的内容,如果想滚动一个ViewGroup则再给他嵌套一个外层,滚动外层即可
总结
- view获取自身坐标:getLeft(),getTop(),getRight(),getBottom()
- view获取自身宽高:getHeight(),getWidth()
- motionEvent获取坐标:getX(),getY(),getRawX(),getRawY()
- 然后是motionEvent的方法:
- getX():获取点击事件相对控件左边的x轴坐标,即点击事件距离控件左边的距离
- getY():获取点击事件相对控件顶边的y轴坐标,即点击事件距离控件顶边的距离
- getRawX():获取点击事件相对整个屏幕左边的x轴坐标,即点击事件距离整个屏幕左边的距离
- getRawY():获取点击事件相对整个屏幕顶边的y轴坐标,即点击事件距离整个屏幕顶边的距离