一、背景

在上一篇文章View的位置中,介绍了top, left, bottom, right这几个坐标,我们知道了这几个坐标是view与其所在的父容器的相对位置。那x,y,translationX,translationY是做什么的?这几个坐标是在Android API 11(Android3.0)之后加进来的。

三、代码

还是之前的那个例子

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/block1"
        android:layout_width="match_parent"
        android:layout_height="200px"
        android:background="@color/blue"/>

    <RelativeLayout
        android:id="@+id/block2"
        android:layout_below="@+id/block1"
        android:layout_width="match_parent"
        android:layout_height="2000px"
        android:background="@color/red">

        <Button
            android:id="@+id/button"
            android:layout_width="250px"
            android:layout_height="100px"
            android:layout_marginLeft="30px"
            android:layout_marginTop="30px"
            android:text="button"/>
    </RelativeLayout>
</RelativeLayout>

(当然用px在xml里是绝对不推荐,但是为了这次log能够看的清楚写的测试程序)
那么打出log看一看这几个控件的实际位置:

03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ button, top:30,left:30:bottom:130,right:280
03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ button, x:30.0,y:30.0:translationX:0.0,translationY:0.0
03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ block1, top:0,left:0:bottom:200,right:720
03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ block1, x:0.0,y:0.0:translationX:0.0,translationY:0.0
03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ block2, top:200,left:0:bottom:1118,right:720
03-16 00:02:41.607 4442-4442/com.example.sakuraisho.scrollapp V/position﹕ block2, x:0.0,y:200.0:translationX:0.0,translationY:0.0

四、结论

先给出结论,View在平移的过程中,top和left表示的是原始左上角的位置信息,其值不会发生改变。而在平移过程中发生改变的是x,y,translationX,translationY。x,y是View左上角的坐标,translationX,translationY是平移的距离。即

x = left + translationX
y = top + translationY

五、验证

方法一:
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams();
params.leftMargin +=300;
button.requestLayout();

如果采用上面的方式,translationX和translationY依旧是0,但是left会发生变化,这说明直接上面的做法是直接改变了view的位置,并非是平移。那么什么时候才能出现translationX不为0的时候?

方法二:

都说动画实际并不能改变View的位置,甚至连响应事件都不能移动。当然这个相应事件的问题在属性动画时解决掉了,那就来试试用属性动画会产生什么效果。

log(...);
ObjectAnimator.ofFloat(button, "translationX", 0, 100).setDuration(2000).start();
handler.sendEmptyMessageDelayed(1, 3000);

在动画开始前记录下button的位置,当动画结束后再记录下位置,如下:

03-16 00:39:49.500 25085-25085/com.example.sakuraisho.scrollapp V/position﹕ button, top:30,left:30:bottom:130,right:280
03-16 00:39:49.500 25085-25085/com.example.sakuraisho.scrollapp V/position﹕ button, x:30.0,y:30.0:translationX:0.0,translationY:0.0
03-16 00:39:52.503 25085-25085/com.example.sakuraisho.scrollapp V/position﹕ after button, top:30,left:30:bottom:130,right:280
03-16 00:39:52.503 25085-25085/com.example.sakuraisho.scrollapp V/position﹕ after button, x:130.0,y:30.0:translationX:100.0,translationY:0.0

惊喜的发现,translationX平移了100,x的值也变为了130,而原始的坐标并没有变化!

按钮的点击事件

突然有点疑惑,View是真正被转移了吗?还是说x,translationX只是一个暂存的状态,否则要原始的坐标left做什么呢?如果button上有点击事件的话,当动画结束后,点击事件能正确响应吗?

经过测试,button在动画中,动画结束后,均能够正确响应点击事件。所以单纯的理解好这几个坐标所代表的意义就好!书上说的什么Adroid3.0以前动画是对View的影像进行操作,不改变View的位置参数宽高等,并不影响坐标的意义!

改变了view的layoutparams就改变了view的原始的坐标。而通过动画改变的位置是会保留原始的坐标。但这并不代表在原位置保存了原始的view!不要混淆。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐