Android自定义动画之曲线轨迹

Android支持的动画系统大体上分为两种,分别是View AnimationProperty Animation,总体来说推荐使用Property Animation,Property Animation更强大,但是如果View Animation能满足你的需要的话或者因为条件限制只能使用View Animation,那么当然还是选择View Animation。功能更多更强大的东西意味着你要付出更多的努力来实现和维护它,这是游戏规则。闲话扯远了,回到主题,还有一点就是Property Animation在API Level 11才开始支持。更多的介绍可以参看官方的文档。

这两种方式的使用都还比较简单。在View Animation中通常是实现translate、alpha、scale和rotate其中的一种或多种(具体的可以通过写代码或者配置XML实现,其实最终都是一样的)。在Proerty Animation中也是指定要进行动画的属性,比如x、y、alpha、rotation或者scaleX(scaleY)等等。参考docs和samples可以很快实现基本动画。

但是有时候我们需要的比这些基础功能要稍微复杂点的东西,那么就需要我们来扩展了。现在我们来实现一个运动轨迹是曲线的动画,基础的translate动画的运动轨迹是点到点的,直线的。

在Property Animation中大家可以参考http://code.google.com/p/android-path-animation/这个例子来实现,简单明了。例子的作者也是Android Project的Committer,所以还是很有分量的。

在View Animation中就需要自己定义一个动画来实现了,TranslateAnimation的运动轨迹是直线,既然我们需要曲线的轨迹,那么想当然我们只需要修改部分代码就可以了。原本想来继承TranslateAnimation这个类的,但是发现这个类里面我们需要的变量和方法都是private或者package,所以只好把这个类的代码拷贝一份自己来写,看来官方也不想让我们来继承原本的这几个基础动画啊(不知道是不是我还没有找到自定义动画的窍门)。不过目前就先实现一个再说,先追求有,再追求好。“红绿红”确实是个比较有效和重要的规则。在这里我们需要一个公式(貝茲曲線)。简单的介绍一下,这个公式在图形学中非常有用,线性、二次或者高阶曲线代表不同的曲线类别,比如直线、抛物线或者波形线。在这里我们用二阶的,需要注意的就是一个拐点的问题,我们称为控制点,这个控制点选取的不一样,出来的曲线效果就不一样,这个在感性上很容易理解。
假设三个点P0、P1、P2,公式参照wiki二阶公式。计算的Java代码如下

	private long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
		return Math.round((Math.pow((1 - interpolatedTime), 2) * p0)
				+ (2 * (1 - interpolatedTime) * interpolatedTime * p1)
				+ (Math.pow(interpolatedTime, 2) * p2));
	}

这里就是把公式转化成了Java代码,没有任何其它的加工。完整的代码参见ArcTranslateAnimation.java,在这个例子中我们控制点的选择比较简单(mFromXDelta, mToYDelta),这里有个建议或者说是常用的就是通常用起点和终点的切线的交点来作为控制点,当然控制点你可以自己选择,按照自己的想法用公式计算出来。

其它的都没有什么需要特别注意的地方,按照普通的Animation使用的方式来使用就可以了。目前只能通过写Java代码来使用这个动画,如果想要通过配置XML来使用,还要完善这个类的部分代码,比如添加新的构造函数,配置它的attrs.xml等等,可能有些方法无法使用既有的,好些想用的方法都是private和package。

大家如果有什么好的建议或者实现方式,欢迎提出来,Android的UX还是不如iOS,要不然果粉还是那么多那么疯狂呢?

哦,差点忘记了,还要稍微提到一下,还有一种帧动画,在Docs上这是被列入Android支持的三种动画系统之一,但个人认为帧动画和渐变动画这是两种不同的方式,从动画通用的分类来说可以这么分,并不限定于Android,有兴趣可以找相关材料阅读下。

更多资料
http://developer.android.com/reference/android/animation/package-summary.html
http://developer.android.com/guide/topics/graphics/animation.html
http://www.math.ubc.ca/~cass/gfx/bezier.html