注册

Android | 彻底理解 View 的坐标

Android | 彻底理解 View 的坐标

前言

如果你是一位从事 Android 原生开发的工程师,那么肯定会对 View 的各种坐标感到迷惑,不理解他们的真正含义。因为曾经我也和你们一样,面对他们时感到陌生和害怕。现在我将这些知识点整理成文,希望可以给大家一些帮助。

View 的坐标分为四大类:位置坐标,内容滚动坐标,平移坐标,触摸坐标。 通过阅读本文,读者能够在理解各种 View 坐标的基础上,今后在面对动画和触摸事件的处理会更加的游刃有余。

预备知识

如果你对以下知识有过了解,阅读本文将会很轻松。

  1. 了解 View 的属性动画;View 触摸事件的分发;View 的测量、布局过程
  2. 了解 Kotlin 基础语法

环境

文中所有的代码和运行截图,基于以下开发环境。
Android Studio 4.1.1
Kotlin 1.4.20
程序运行系统 Android 5.1

View 的位置坐标

View 的位置坐标是我们日常开发中最常见的一类坐标,分别是左、上、右、下,获取他们的值也很简单。

getLeft()
getTop()
getRight()
getBottom()

如上所示,通过 View 的上面四个方法,就可以获取到 View 的位置坐标了。需要注意以下三点。

1. (left,top) 代表 View 的左上角坐标,(right,bottom) 代表 View 的右下角坐标
2. 位置坐标是一种相对于父容器的坐标,即坐标系原点是父容器的左上角
3. 位置坐标不会因为 View 的内容滚动、View 的平移而改变,他们在 View 的测量、布局过程结束后就确定了

View 的内容滚动坐标

通过 View 的下面两个方法,可以得到 View 内容滚动后的左上角坐标。

getScrollX()
getScrollY()

需要注意 View 的内容滚动坐标是相对于 View 自身的坐标,即坐标系原点是 View 自身的左上角,并不是父容器。 如下伪代码和运行截图所示,绿色区域是一个 TextView ,当我们点击绿色区域的时候,TextView 的内容会向右滚动 100px的距离,根据运行后的截图,可以得出如下结论。

1. View 的位置坐标并不会因为 View 的内容滚动后而发生改变,这在上面已经说明过
2. 当一个 View 的内容从左向右滚动时,getScrollX() 是负值,同理当一个 View 的内容从上往下滚动时,getScrollY()也是负值。反之,从右向左,从下往上就是正值

viewBinding.tvScroll.scrollTo(-100,0)

初始坐标.png

向右滚动100px.png

View 的平移坐标

读者在实际开发中,或多或少都接触过 View 的属性动画,大概是平移、旋转、缩放三种。而平移的运用场景在 Android 中实在是太多了,基本你能看到的 View 滑动效果,都是通过属性动画的平移来实现的。通过下面两个方法,可以得到 View 左上角的平移坐标。需要注意 View 的平移坐标同样是相对于 View 自身的坐标,即坐标系原点是 View 自身的左上角,并不是父容器

getTranslationX()
getTranslationY()

当然在你需要的时候,通过 View 的下面两个方法,仍然可以获得 View 相对于父容器的平移坐标。

getX()
getY()

他们两者之间的数学关系如下

getX() = getLeft() + getTranslationX()
getY() = getTop() + getTranslationY()

如下图伪代码和运行截图所示,绿色区域仍然是一个 TextView,当我们点击绿色区域的时候,使用属性动画,让 TextView 向右平移 100px,根据运行后的截图,可以得出如下结论。

1. View 的位置坐标不会随 View的平移而改变
2. 和 View 的内容滚动不一样,View 的平移是整个 View 都向右平移
3. 向右平移 getTranslationX() 是正值,同理向下平移 getTranslationY()也是正值。反之就是负值

val translationXAnim = ObjectAnimator.ofFloat(viewBinding.tvScroll,"translationX",0f,100f).setDuration(2*1000)
translationXAnim.start()

初始坐标.png

向右平移100px.png

这里读者思考一个问题,如果让你实现一个 View 的滑动效果时,选择内容滚动还是属性动画平移? 很显然,平移相对内容滚动有诸多优点,首先是平移坐标的正负值符合人们的直观感受,其次平移是整个 View 的平移,实际应用场景更多,没有明显的缺点。

View 的触摸坐标

View 的触摸坐标和触摸事件是相关联的,获取触摸坐标有如下两组方法。

第一组,获取 View 触摸点相对于 View 自身左上角的坐标

eventX = event.getX()
eventY = event.getY()

第二组,获取 View 触摸点相对于设备屏幕左上角的坐标

rawX = event.getRawX()
rawY = event.getRawY()

注意上面伪代码中 event 的类型是 MotionEvent,读者可以通过调用 View 的 setOnTouchListener 方法,或重写 View 的 onTouchEvent 方法,来使用这个对象。

如下运行截图所示,绿色区域仍然是一个 TextView,不过这里为它设置了 50px 的左边距和 50px 的上边距。点击绿色区域的任意一处,你都会看到,rawX 和 eventX 始终相差 50px,rawY 和 eventY 始终相差 75px。 根据上面的分析 rawY 和 eventY 也应该相差 50px 才对?其实多出来的 25px 是屏幕状态栏的高度,这证实了上面的结论。

1. event.getX() 和 event.getY() 是 View 触摸点相对于 View 自身左上角的坐标
2. event.getRawX() 和 event.getRawY() 是 View 触摸点相对于设备屏幕左上角的坐标

触摸坐标.png

通过下图,读者或许能够更好理解。

触摸坐标

写在最后

本文是对 View 坐标的一次实践与总结,希望本文能够给读者一点帮助。

原文链接:https://juejin.cn/post/7037320714935861284?utm_source=gold_browser_extension

0 个评论

要回复文章请先登录注册