网上有不少人把view的坐标和点击事件的坐标 混为一谈
一、View的相关坐标和位置
先来看一张图,对这几个值有个大概了解,下面再进行详细的分析
先来了解一个概念:
view动画不改变view的真实位置,就是肉眼看上去,view位置发生了变化,但是它的点击区域还是在原来的位置。
属性动画和setTranslationX/setTranslationY ,会改变显示位置和真实位置
上图中view1是初始位置,通过执行setTranslation函数,得到的view2位置,其中left,top,right,bottom这几个值不会改变
1、left,top,right,bottom
View 的位置主要由它的四个顶点的位置来决定,分别对应 View 的四个属性:left top right bottom。对应的函数是getLeft,getTop,getRight,getBottom
left: View 左上顶点相对于父容器的横坐标
top: View 左上顶点相对于父容器的纵坐标
right: View 右下顶点相对于父容器的横坐标
bottom: View 右下顶点相对于父容器的纵坐标
这几个值表示的是view的真身位置,它表示哪里,点击区域就在哪里。和肉眼在屏幕上看到的位置可能不一样
2、 X,Y
从 Android 3.0 开始,View 增加了 x,y,translationX 和 translationY。
x,y 同样是 View 左上角相对父容器的坐标,但不同于 left 和 top ,这两个坐标点的值并一定都是相等的。
而不相等的情况是由 translationX 和 translationY 值的设置引起的。
3、 translationX,translationY
android开发艺术探索中,关于translationX的讲解是错误的。真实情况是,translationX是view 相对于它自身位置的偏移量
也就是肉眼看到的view的位置,和真实的view的位置的偏移量。
从上图可以得知:x = left + translationX
二、点击事件的XY坐标
上面的"蓝点"表示的一次点击事件。
涉及到的方法一共有下面几个:
view获取自身坐标:getLeft(),getTop(),getRight(),getBottom()
view获取自身宽高:getHeight(),getWidth()
motionEvent获取坐标:getX(),getY(),getRawX(),getRawY()
上面几个参数表达的含义很清晰, 比较让人疑惑的是书中提到的,View的x,y, translationX, translationY这4个参数的含义。
含义如下:
translationX,translationY: View显示相对于初始位置的偏移量.
x,y: View最终可见时的坐标,是View的left,top位置加上translationX,translationY.
left, top: 是View初始在ViewGroup布局时的左上角坐标。
这几个参数是理解View动画的基础。
在View Animation中,对View应用Animation并没有改变View的left, top, right, bottom的属性值,动画的实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,draw后再改变参数invalidate,这样虽然View的大小或旋转角度等改变了或进行了平移,但View的实际属性没变,所以有效区域还是应用动画之前的区域,比如你把一按钮放大两倍,但还是放大之前的区域可以触发点击事件。(注意:使用属性动画可以解决实施动画前后点击事件响应区域不一致的问题。)
跟位置有关的参数有3个,以X坐标为例,可以通过getLeft(),getX(),getTranslateX()获得,若有一Button btn2,布局时其坐标为(40,0):
//应用动画之前
btn2.getLeft(); //40
btn2.getX(); //40
btn2.getTranslationX(); //0
//应用translationX动画
ObjectAnimator oa=ObjectAnimator.ofFloat(btn2,"translationX", 200);
oa.setDuration(2000);
oa.start();
/*应用translationX动画后
btn2.getLeft(); //40
btn2.getX(); //240
btn2.getTranslationX(); //200
*/
//应用X动画,假设没有应用之前的translationX动画
ObjectAnimator oa=ObjectAnimator.ofFloat(btn2, "x", 200);
oa.setDuration(2000);
oa.start();
/*应用X动画后
btn2.getLeft(); //40
btn2.getX(); //200
btn2.getTranslationX(); //160
*/
无论怎样应用动画,原来布局时的位置通过getLeft()获得,保持不变。
X是View最终显示时的位置;
translationX为最终显示位置与布局时初始位置这差。
所以ObjectAnimator.ofFloat(), 若就用translationX即为在原来基础上移动多少,若用X为最终要移动到X轴的哪个位置。
getX()的值为getLeft()与getTranslationX()之和。