Android 自定义View之坐标系(一)
前言
本文主要阐述的是Android坐标系,便于对于Android视图界面坐标的一个简单了解。在Android任何视图中,不管是对于控件的摆放位置、触摸点、自定义控件绘制等等都脱离不开坐标系。Android坐标系是一个三维坐标,Z轴向上,X轴向右,Y轴向下。这三维坐标的点处理就能构成Android丰富的界面或者动画等效果,所以Android坐标系在整个Android界面中的重要性就不言而喻。
Android屏幕区域划分
在Android坐标系前,我们先来了解一下Android屏幕的区域划分。Android屏幕的区域主要分为五个区域分别为:状态栏区域、ActionBar区域、View布局区域、应用程序区域、屏幕区域,当相互之间又存在嵌套关系。具体如下图:
通过上图依次列出区域的一些坐标或者度量方式:
状态栏高度获取
//第一种方式//该方法依赖于WMS(窗口管理服务的回调),使用此方法一定要等界面渲染结束Rect rect= new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);int statusBarHeight = rectangle.top;//第二种方式/** * 获取状态栏高度 * @param context */ Resources resources = context.getResources(); int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); int height = resources.getDimensionPixelSize(resourceId);//此次获取状态栏高度//第三种方式/** * 通过反射方式获取状态栏高度 * @param context * @return */ int statusHeight = -1; try{ Class<!--?--> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); intheight = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height);//此次获取状态栏高度 }catch(Exception e) { e.printStackTrace(); }
ActionBar高度获取
//第一种方式int actionBarHeight = getActionBar().getHeight();//第二种方式TypedValue tv = new TypedValue();if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());}
View布局区域
//第一种方式Rect rect = new Rect();getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);//第二种方式//可见当执行onResume和onPause时,onWindowFocusChanged都会被调用。此时界面已渲染结束 @Overridepublic void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);if (hasFocus) { int width = view.getMeasuredWidth();//获得宽度 int height = view.getMeasuredHeight();//获得高度}}//第三种方式view.post(new Runnable() { @Override public void run() { int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight(); } }) //第四种方式 view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight(); } });
应用程序区域高度获取
Rect rect = new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
屏幕区域高度获取
//第一种方式,该方式在4.1版本后已过时。 Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); int height = display.getHeight();//第二种方式 Display defaultDisplay = getWindowManager().getDefaultDisplay(); Point point = new Point(); defaultDisplay.getSize(point); int x = point.x; int y = point.y;//第三种方式 Rect outSize = new Rect(); getWindowManager().getDefaultDisplay().getRectSize(outSize); int left = outSize.left; int top = outSize.top; int right = outSize.right; int bottom = outSize.bottom; //第四种方式 DisplayMetrics outMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(outMetrics); int widthPixels = outMetrics.widthPixels; int heightPixels = outMetrics.heightPixels;//第五种方式 Point outSize = new Point(); getWindowManager().getDefaultDisplay().getRealSize(outSize); int x = outSize.x; int y = outSize.y;//第六种方式 DisplayMetrics outMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics); int widthPixel = outMetrics.widthPixels; int heightPixel = outMetrics.heightPixels;
注意:在Activity的onCreate()或者onResume()中去获得View的高度的时候不能正确获得宽度和高度信息,这是因为 View的measure过程和Activity的生命周期不是同步执行的,因此无法保证Activity执行了onCreate、onStart、onResume时是否已经完成了界面测量,如果还没有测量完,那么获得的宽高就是0。
Android坐标系
前面我们通过图了解了一下Android屏幕的划分及相应区域尺寸的获取方式,那么接下里我们将分析一下与区域相关的Android坐标系。在Android中的坐标系可以分为三类:屏幕坐标系
、布局坐标系
和视图坐标系
。
屏幕坐标系
该坐标系是以屏幕的左上角为原点(0, 0), 水平向右代表 x 方向的正方向, 垂直向下代表 y方向的正方向。
布局坐标系
该坐标系是以View布局区域的左上角为坐标原点, 水平向右代表 x 方向的正方向,垂直向下代表 y 方向的正方向。
视图坐标系
该坐标系是在View绘制过程中,绘制的内容将该坐标系作为参考,来绘制View也就是内容在View里面的位置。
以下为视图(View)常用到的获取坐标方法,需要注意的是一下几个方法是相对于父容器而言的。
视图(View)相关方法 | 方法说明 |
---|---|
view.getLeft() | 当前View的左边缘与它父View的左边缘的距离(视图坐标); |
view.getRight() | 当前View的右边缘与它父View的左边缘的距离(视图坐标); |
view.getTop() | 当前View的上边缘与它父View的上边缘(顶部)的距离(视图坐标); |
view.getBottom() | 当前View的下边缘与它父View的上边缘(顶部)的距离(视图坐标); |
View.getTranslationX() | 当前View在X轴的偏移量。初始值为0,向左偏移值为负,向右偏移值为正;(常见于属性动画中) |
View.getTranslationY() | 当前View在Y轴的偏移量。初始值为0,向上偏移为负,向下偏移为证;(常见于属性动画中) |
View.getX | 当前View在X轴的偏移量。初始值为0,向左偏移值为负,向右偏移值为正; |
View.getY | 当前View在Y轴的偏移量。初始值为0,向上偏移为负,向下偏移为证; |
具体方法如下:
以下为视图(View)获取高宽方法:
View宽高方法 | 方法说明 |
---|---|
getWidth() | 当前View的宽度,即getRight()-getLeft()。 |
getHeight() | 当前View宽度,即getBottom()-getTop()。 |
注意:当在使用以上两个方法的时候一定要在View测量结束(渲染完成)后,不然获取到的值是不准确的(都为0)。
接下来将说明在View使用中MotionEvent类相关坐标方法说明(涉及到相对坐标和绝对坐标),相对坐标是相对View本身而言的,即在View范围内的触摸点到View上边缘和左边缘的距离;而绝对坐标是相对屏幕的,即在View范围内的触摸点到屏幕上边缘和左边缘的距离:
MotionEvent类相关坐标方法 | 方法说明 |
---|---|
getX() | 触摸中心点与该View左边缘的距离(相对坐标) |
getY() | 触摸中心点与该View上边缘的距离(相对坐标) |
getRawX() | 触摸中心点与屏幕左边缘的距离(绝对坐标) |
getRawY() | 触摸中心点与屏幕上边缘的距离(绝对坐标) |
具体方式如下图:
结束
对于坐标系本文就阐述到这里,本文介绍坐标系目的有两个:其一主要方便大家再次的了解Android坐标系及相关的API使用;其二为接下来即将阐述的自定义View做一个铺垫,因为坐标概念只是一个基础对于自定义View也是相当重要的一部。
更多相关文章
- android控件的对齐方式(转)
- android app模拟 persistent 属性可以保活且正常升级的一种方式
- android控件的对齐方式
- Android Studio添加aar依赖的两种方式
- 转载 android 利用ksoap2方式连接webservice
- android跨进程通讯一:android中跨进程通讯的4种方式
- Android 使用非阻塞的方式读写串口
- android坐标系相关知识点
- Android选项卡TabHost方式实现