1、概述
Android系统中德坐标系统比较复杂,各种绝对和相对坐标用起来真的很容易混淆。
开发中经常用到View的一些坐标,一些值经常搞混,今天就来总结下。
2、Android View layout()
android.view.View.layout(int l, int t, int r, int b)
l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent
文档上写的很清楚,这四个参数都是相对于父视图来说的。
layout的过程就是确定View在屏幕上显示的具体位置,在代码中就是设置其成员变量mLeft,mTop,mRight,mBottom的值,这几个值构成的矩形区域就是该View显示的位置,不过这里的具体位置都是相对与父视图的位置。mLeft代表当前view.layout的这个view的左边缘离它的父视图左边缘的距离,mTop指当前view的上边缘离父视图上边缘的距离。而以此为界,mRight所指的是当前view的右边缘离父视图左边缘的距离(mLeft+自己的宽度),mBottom也是指当前view的下边缘离父视图的上边缘的距离。至于为何如此,大概是因为坐标系的缘故,坐标中的任何点都必须以(0,0)为起点,XY轴为衡量。
视图左侧位置 view.getLeft()
视图右侧位置 view.getRight()
视图顶部位置 view.getTop();
视图底部位置 view.getBottom();
这四个方法所获取到的各个左上右下的值与layout的四个参数代表的是一样的,都是相对父视图的左边缘与上边缘。
3.View getTranslationX getTranslationY
he horizontal location of this view relative to its left position. This position is post-layout, in addition to wherever the object's layout placed it.
相对于自己左边(上边)的距离,移动后的数值。
translateX是相对于left属性来进行的平移,比如left=20,此时调用setTranslationX(30)后,就是相对于left(而不是它上一次的translationX后的位置)往右平移30px,若此时再调用调用setTranslationX(40),之前的30px值就被覆盖,改为相对于left右移40px。
X也是相对于父容器的当前View的位置,就像前面的等式所说,x = left + translationX;所以每一次setTranslationX都会导致getX值的变化,而left的值并不会改变。
4.View getX() getY()
android.view.View.getX()
The visual x position of this view, in pixels. This is equivalent to the translationX property plus the current left property.
android.view.View.getY()
The visual y position of this view, in pixels. This is equivalent to the translationY property plus the current top property.
意思就是说获取到实际的View的x y 值,该值也是相对父视图而言的,
并且该值 getX = getLeft + getTraslationX。最后得出的值也是相对父视图来说的。
5.LayoutParams getMargins
The left(top right bottom) margin in pixels of the child.
获取到该View的四个边的边距,有可能是附近的其他子view,也有可能是相对父视图。要看实际的情况分析
一般来说,我们要动态的移动子view的位置,可以使用setmargins 相对父视图来实现,前提是不能跟其他子view发生关系
6.getPadding
Returns the left(top right bottom) padding of this view.
获得该view的内部缩进值(自己内部),相对于Margin(相对于其他view或ViewGroup).
综上,要获取到view准确的位置,要根据设定去拿值
比如,给view设置margin后,然后用translation移动,最后值就可以用getmargin + getTranslation来计算。etc
7.1.View的getX()、getLeft()、getTranslationX()
要清楚他们这几个方法的区别,就需要知道他们的"x" 、"left"、"translateX"代表的含义(left、right、bottom、top 或 X、Y等类似),这里就直接说结果了。
这里以left举例:
他们之间的关系为:
x = left + translateX;
这里根据它的源码就可以看出:
/**
* The visual y position of this view, in pixels. This is equivalent to the
* {@link #setTranslationY(float) translationY} property plus the current
* {@link #getTop() top} property.
*
* @return The visual y position of this view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getY() {
return mTop + getTranslationY();
}
区别的在于:
left属性是在布局时决定的,代表相对于它的父容器的初始位置(layout时的位置),具体可以看源码中mLeft的说明,以及它被调用的地方,都是layout或者setLeft等方法中,还有一个可能会调用的比较多的方法offsetLeftAndRight()。
translateX是相对于left属性来进行的平移,比如left=20,此时调用setTranslationX(30)后,就是相对于left(而不是它上一次的translationX后的位置)往右平移30px,若此时再调用调用setTranslationX(40),之前的30px值就被覆盖,改为相对于left右移40px。
X也是相对于父容器的当前View的位置,就像前面的等式所说,x = left + translationX;所以每一次setTranslationX都会导致getX值的变化,而left的值并不会改变。
总结:left是布局时决定的属性,在translationX的平移中和setX()的平移中left属性并不会发生改变,translationX平移会导致getX()值得改变,反过来一样。
7.2.getX()与getRawX()
MotionEvent的getX()与getRawX()其实区别就一个:
getX()是相对于自身这个View(被Touch的)的X轴位置,
getRawX()是相对于整个屏幕的X轴位置。
它们与View的上述方法区分性还是很强的,不容易混淆。