Android自定义控件坐标系解析

龙旋

共 6244字,需浏览 13分钟

 · 2021-05-18

自定义控件要想彻底的把握,掌握Android各种坐标系及一些API的坐标含义毫无疑问是不可忽视的技能,对于控件的摆放位置、触摸点、控件绘制等都离不开坐标系,所以学习自定义控件之前我们就先来谈一下Android坐标系。


一、Android屏幕坐标系和数学坐标系的区别


(1)、在数学坐标系中以xy轴的交点为坐标原点,x轴向右为正方向,y轴向上为正方向,这对于童鞋们来说已经再熟悉不过了,如图:

(2)、而在手机屏幕上的坐标系与数学坐标系还是有差别的,移动设备一般定义屏幕左上角为坐标原点,x轴向右为正方向,y轴向下为正方向,如图:


二、Android屏幕区域的划分


Android屏幕区域主要划分为五个区域分别为:状态栏区域、ActionBar区域、View布局区域、应用程序App区域、屏幕区域,相互之间又存在嵌套关系。如图所示:



下面我们来看看各个区域高度的获取:


(1)、状态栏区域高度获取:

        //第一种方式,使用此方法一定要等界面渲染结束        Rect rect = new Rect();        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);        int statusBarHeight = rect.top;        
//第二种方式,获取状态栏高度 Resources resources = this.getResources(); int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); int height = resources.getDimensionPixelSize(resourceId);//此次获取状态栏高度  
//第三种方式,通过反射方式获取状态栏高度 int statusHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int intheight = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); //获取状态栏高度            statusHeight = this.getResources().getDimensionPixelSize(intheight);  } catch (Exception e) { e.printStackTrace(); }


(2)、ActionBar区域高度获取:

        //第一种方式,此方法要等界面渲染结束        int actionBarHeight = getSupportActionBar().getHeight();
//第二种方式 TypedValue tv = new TypedValue(); if (this.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { int actionBarHeightOther = TypedValue.complexToDimensionPixelSize(                    tv.data, this.getResources().getDisplayMetrics());  }


(3)、View布局区域高度获取:

  //第一种方式  Rect rect = new Rect();  getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
//第二种方式 //可见当执行onResume和onPause时,onWindowFocusChanged都会被调用。此时界面已渲染结束 @Override public 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(); }    });


(4)、应用程序App区域高度获取:

 Rect rect = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);


(5)、屏幕区域高度获取:

        //第一种方式,该方式在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 outSizeOther = new Point(); getWindowManager().getDefaultDisplay().getRealSize(outSizeOther); int x1 = outSizeOther.x; int y1 = outSizeOther.y;
//第六种方式 DisplayMetrics outMetrics1 = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics1); int widthPixel = outMetrics1.widthPixels; int heightPixel = outMetrics1.heightPixels;


特别注意:上面这些方法最好在Activity的onWindowFocusChanged()方法或者之后调用,因为只有这时候才是真正的显示完全。



三、Android坐标系的分类


上面我们分析了Android屏幕区域的划分,接着我们分析一下与区域相关的Android坐标系,在Android坐标系中可以分为:屏幕坐标系,视图坐标系。


(1)、屏幕坐标系


屏幕坐标系我们前面在和数学坐标系的区别已经介绍过了,以屏幕左上角为坐标原点,x轴向右为正方向,y轴向下为正方向,如图所示:




(2)、视图坐标系


视图坐标系在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,向左偏移值为负,向右偏移值为正;返回值为getLeft()+getTranslationX(),当setTranslationX()变getLeft()不变时,getX()变。
View.getY当前View在Y轴的偏移量。初始值为0,向上偏移为负,向下偏移为正;返回值为getTop()+getTranslationY(),当setTranslationY()变getTop()不变时,getY()变。


为了解释清楚这些方法,准备了张图,如图所示:



此时我们可以获取视图(View)宽高的方法:


View宽高方法                                        方法说明
getWidth()当前View的宽度,即getRight()-getLeft()
getHeight()当前View宽度,即getBottom()-getTop()


需要注意的是使用以上方法的过程中要在View测量结束即渲染完成后,不然获取到的值为0。



我们再来看看手指触摸屏幕时MotionEvent提供的一些方法解释:


MotionEvent坐标方法                                     方法说明
getX()触摸中心点与该View左边缘的距离(相对坐标)
getY()触摸中心点与该View上边缘的距离(相对坐标)
getRawX()触摸中心点与屏幕左边缘的距离(绝对坐标)
getRawY()触摸中心点与屏幕上边缘的距离(绝对坐标)


为了解释清楚这些方法,准备了张图,如图所示:



今天的内容就到这啦,本文主要就是阐述View里常用方法及坐标相关的概念,也是为后期的内容做铺垫。

浏览 26
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报