Animation仅仅是视觉上的移动,实际位置并没有动 

startAmimation()是开启一条线程来执行动画,动画执行完成后可以再用监听从

onAnimationEnd()方法中用

setMargins(location[0],0,0,0);
setLayoutParams();


来改变控件的真是位置,但是只有当线程结束后才能获取到变化后的真是位置(在线程中获取到的位置信息在线程结束前世不会改变的【起码还没有锁定到它的位置】)
我是另外设置了一个按钮来实现获取其坐标的信息在动画执行完成后能实现预期的变化
如果你的xml中设置了 

android:layout_CenterHorizental="true"的话


在代码中在运用

setMargins(location[0],0,0,0);


是没有作用的


在new一个AnimationSet中传入true则所有的Animation共用Interpolator。

提醒自己:

以后编码的时候如果碰到自己预想之外的情况,

那么原因是 

1.自己逻辑错误(认真检查)

2.新的方法或类没有理解到位(即使自己认为已经理解好了),锁定自己代码所添加功能中所有新知识,逐个再次详细了解(这个时候一定不能急不能慌,不管这个项目多么紧急)。

3.循环1、2步骤

我的问题:

刚开始没有用好是因为没有弄清楚 TranslateAnimation 几个构造函数的含义:

先列出其含义如下:

在android动画中,最常用的一个莫不是TranslateAnimation了,这个类主要负责实现控件的动态位移,经常被用做指示器的移动动画。比如qq安卓客户端的指示器,如下图。 

 

android动画放哪里_构造函数


       关于TranslateAnimation几个构造函数的参数意义,曾困惑我不少时间,参考官方文档和网上的讲解,通过试验总结出一些自己的理解,如果有误敬请指正。

       TranslateAnimation共有三个构造函数,分别是:

android动画放哪里_android动画放哪里_02


其中,我们最常用的是后两个,现在主要想说明一下我对后两个函数参数的理解。

        先说第二个构造函数:TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, floattoYDelta)。

        Delta,顾名思义表示的是一个后一个和前一个的差值。XDelta即表示在X方向上的差值,同理YDelta表示在Y方向的差值。若XDelta>0,则说明控件向右侧发生移动,否则向左侧移动,Y轴方向是相同的道理。现在来说下各个参数的意思:

        fromXDelta:控件的开始移动前的位置,为什么是Delta呢?因为在此之前,该控件可能已经发生过了位移,因此它已经偏离了控件最初始的位置。因此采用了距离最初始位置的偏移量。

        toXDelta:相同道理,想要移动的终点位置距离最初始位置的偏移量。记住,一定不要混淆的是,不要把这个最初始位置当成是移动开始前控件的位置,否则将会发生错误移动。

        后面两个参数表示Y方向上的,和X方向上的同理。需要说明的是,这个是绝对偏移量,是以像素为单位进行计算的。

        再来说说第三个构造函数。

        当X方向或者Y方向上的Type选择为Animation.ABSOLUTE时候,表示为绝对像素,此时XValue和YValue参数的含义和第二个构造函数相同。

        而当X方向或者Y方向上的Type选择为Animation.RELATIVE_TO_SELF或者Animation.RELATIVE_TO_PARENT时候,则表示相位移量了,举个例子来说,如果在X方向上选择Animation.RELATIVE_TO_SELF,那么当XValue=1.0f(就是百分比咯)时,则偏移量为一个自身宽度。如果在X方向上选择Animation.RELATIVE_TO_PARENT时,则偏移量为一个父控件宽度。Y方向是相同的道理,只是把宽度换成了高度而已。

真正移动并且防止用offsetLeftAndRight()出现闪烁

在一些界面上,我们可能需要实现可以移动的按钮等功能,最简单的方式是调用View.layout(),任何布局上的空间都可以支持这种方式移动,上下左右参数值是相对于父viewgroup而言的。


public          void          layout(         int          l,          int          t,          int          r,          int          b)        

         eg.        

         button.layout(newLeft, newTop, newRight,newBottom);



但是这种方式有个缺陷就是,当同一个viewgroup中有控件更新(界面刷新)时,移动的控件会复位,即回到一开始的位置,这常常会让人莫名其妙。

另外一种方法是调用MarginLayoutParams.setMargins(),重新设置控件位置参数来实现控件移动效果。这种方式比较适合RelativeLayout、FrameLayout,AbsoluteLayout,对于LinearLayout,因为最后增加的控件总在最下或最右,所以达不到移动效果,TableLayout也不行。


public          MarginLayoutParams(MarginLayoutParams source)        

         eg.        

         FrameLayout.LayoutParams btnLp = (FrameLayout.LayoutParams)button.getLayoutParams();        

         btnLp.setMargins(newLeft, newTop, newRight, newBottom);           

         button.requestLayout();


Android不建议应用直接调用layout()方法,所以个人建议选择FrameLayout + setMargins()实现控件动态移动效果,还有一个经常搭配使用的方法是bringToFront(),当控件被盖住看不见时相当有用。



用法

如何实现将View向上平移自身高度一半的距离?

 

TranslateAnimation translate = new TranslateAnimation(
 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, 
 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f);
 mView.startAnimation(translate);

问题:当动画结束后,View会跳回到原始位置。

 

改进:

AnimationSet set = new AnimationSet(true);
 TranslateAnimation translate = new TranslateAnimation(
 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, 
 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f);
 set.addAnimation(translate);
 set.setFillAfter(true);
 mView.startAnimation(set);

 

setFillAfter文档说明:

If fillAfter is true, the transformation that this animation performed 

will persist when it is finished. Defaults to false if not set.

设为true之后,界面会停留在动画播放完时的界面。

 

问题:动画结束后界面显示正确,但是View上各控件的实际位置和看上去的位置不对应,

实际位置还在View的原始位置,因此button的点击位置会有问题,和看见的位置有偏差。

 

正确方法:

AnimationSet set = new AnimationSet(true);
 TranslateAnimation translate = new TranslateAnimation(
 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, 
 Animation.RELATIVE_TO_SELF, 0.5, Animation.RELATIVE_TO_SELF, 0);
 set.addAnimation(translate);
 set.setFillAfter(true);
 mView.offsetTopAndBottom(-mView.getHeight() / 2);
 mView.startAnimation(set);

 

先将View向上平移自身高度一半的距离,然后播放动画,从最初位置一直向上移动目标位置。

 

setFillBefore文档说明:

If fillBefore is true, this animation will apply its transformation 
before the start time of the animation. Defaults to true if 
setFillEnabled(boolean) is not set to true.

 

对TranslateAnimation,setFillBefore默认为true,也就是说在动画开始前,先将transformation 

apply到View,这也就是为什么offsetTopAndBottom()后,View依然从原始位置开始运动。

如果setFillBefore设为false,动画播放时会有一个跳动,可以看到View从目标位置跳到原始位置。

 

总结:

使用Animation、AnimationSet框架实现的动画效果,必须先将View放置到最终的目标位置,

然后倒过来,播放从原始位置到目标位置的动画。