Android动画
Android动画
Android提供了多种强大的API,用于动画UI元素和绘制自定义2D和3D图形。
逐帧动画(Frame)
这个动画相对容易理解,它要求我们把动画过程的每张静态图片都收集起来,然后由Android来控制依次显示这些静态图片,再利用人眼“视觉暂留”的原理,给人们造成动画的错觉。
定义逐帧动画非常简单,只需要在<animation-list.../>元素中使用<item.../>子元素定义动画的全部帧,并指定各帧的持续时间即可。定义逐帧动画的格式如下所示:
<?xml version="1.0" encoding="utf-8">
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true"|"false"]>
<item android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer"/>
</animation-list>
上面的android:oneshot控制动画是否循环播放,如果设为true,则动画不会循环播放;否则动画将会循环播放。
需要注意的是,AnimationDrawable代表的动画默认是不播放的,必须在程序中启动动画播放才可以。AnimationDrawable提供了如下两个方法来开始、停止动画:
- start():开始播放动画。
- stop():停止播放动画。
补间动画(Tween)
补间动画就是指我们只需要指定动画开始、结束等“关键帧”,动画变化的“中间帧”由系统计算并补齐。
Android使用Animation代表抽象的动画类,它包括了下面的几个子类:
- AlphaAnimation:透明度改变的动画。创建该动画时要指定动画开始时的透明度、结束时的透明度和动画持续时间。其中透明度可从0变化到1。
- ScaleAnimation:大小缩放的动画。创建该动画时要指定动画开始时的缩放比、结束时的缩放比,并指定动画持续时间。由于缩放时以不同点为中心的缩放效果并不相同,因此指定缩放动画时还要通过pivotX、pivotY来指定“缩放中心”的坐标。
- TranslateAnimation:位移变化的动画。创建该动画时只要指定动画开始时的位置、结束时的位置,并指定动画持续时间即可。
- RotateAnimation:旋转动画。创建该动画时只要指定动画开始时的旋转角度、结束时的旋转角度,并指定动画持续时间即可。由于旋转时以不同点为中心的旋转效果并不相同,因此指定旋转动画时还要通过pivotX、pivotY来指定“旋转轴心”的坐标。
Android为Interpolator提供了下面几个实现类,用于实现不同的动画变化速度:
- LinearInterpolator:动画以均匀的速度改变。
- AccelerateDecelerateInterpolator:在动画开始、结束的地方改变速度较慢,在中间的时候加速。
- CycleInterpolator:动画循环播放特定的次数,变化速度按正弦曲线改变。
- DecelerateInterpolator:在动画开始的地方改变速度较快,然后开始减速。
为了在动画资源文件中指定补间动画所使用的的Interpolator,定义补间动画的<set.../>元素支持一个android:interpolator属性,这属性值可指定为Android默认支持的Interpolator。
自定义补间动画
Android提供了Animation作为补间动画抽象基类,并且为该抽象基类提供了AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation四个实现类。
自定义补间动画时需要继承Animation,继承Animation时关键是要重写该抽象基类的applyTransformation(float interpolatedTime, Transformation t)方法,这个方法中的两个参数分别代表:
- interpolatedTime:代表了动画的时间进行比。无论动画实际的持续时间如何,当动画播放时,这个参数总是自动从0变化到1.
- Transformation:代表了补间动画在不同时刻对图形或组件的变形程度。
Transformation代表了对图片或视图的变形程度,这个对象中封装了一个Matrix对象,对它所包装的Matrix进行位移、倾斜、旋转等变换时,Transformation将会控制对应的图片或视图进行相应的变换。
为了控制图片或视图进行三维空间的变换,需要借助于Android提供的一个Camera(空间变换工具),它提供了下面的一些方法:
- getMatrix(Matrix matrix):将Camera所做的变换应用到指定matrix上。
- rotateX(float deg):使目标组件沿X轴旋转。
- rotateY(float deg):使目标组件沿Y轴旋转。
- rotateZ(float deg):使目标组件沿Z轴旋转。
- translate(float x , float y , float z):是目标组件在三维空间里进行位移变换。
- applyToCanvas(Canvas canvas):把Camera所做的变换应用到Canvas上。
属性动画
从某种角度来看,属性动画是增强版的补间动画可以体现在如下方面:
- 补间动画只能定义两个关键帧在“透明度”、“旋转”、“缩放”、“位移”4个方面的变化,而属性动画可以定义任何属性的变化。
- 补间动画只能对UI组件执行动画,而属性动画几乎可以对任何对象执行动画。
与补间动画相似,属性动画也需要定义如下属性:
- 动画持续时间。默认值为300ms。在属性动画资源文件中通过android:duration属性指定。
- 动画插值方式。在属性动画资源文件中通过android:interpolator属性指定。
- 动画重复次数。指定动画重复播放的次数。通过android:repeatCount属性指定。
- 重复行为。指定动画播放结束后、重复下次动画时,是从开始帧再次播放到结束帧,还是从结束帧反向播放到开始帧。通过android:repeatMode属性指定。
- 动画集。将多个属性动画合并成一组,即可以让属性动画按次序播放,也可以让属性动画同时播放。通过<set../>元素来组合,这个元素的android:ordering属性指定动画是按次序播放,还是同时播放。
- 帧刷新频率。指定每隔多长时间播放一帧。默认值为10ms。
属性动画涉及的API如下:
- Animator:它提供了创建属性动画的基类,基本上不会直接使用该类。通常这个类只用于被继承并重写它的相关方法。
- ValueAnimator:属性动画主要的时间引擎,负责计算各个帧的属性值。它定义了属性动画的绝大部分核心功能,包括计算各帧的相关属性,负责处理更新事件,按属性值的类型控制计算规则。
- ObjectAnimator:是ValueAnimator的子类,允许对指定对象的属性执行动画。
- AnimatorSet:它是Animator的子类,用于组合多个Animator,并指定多个Animator是按次序播放,还是同时播放。
属性动画还需要利用一个Evaluator(计算器),该工具类控制属性动画如何计算属性值。Android提供了如下的Evaluator:
- IntEvaluator:用于计算int类型属性值的计算器。
- FloatEvaluator:用于计算float类型属性值的计算器。
- ArgbEvaluator:用于计算以十六进制形式表示的颜色值的计算器。
- TypeEvaluator:计算器接口,我们可以通过实现这个接口来实现自定义计算器。
1.使用ValueAnimator创建动画
- 调用ValueAnimator的ofInt()、ofFloat()或ofObject()静态方法创建ValueAnimator实例。
- 调用ValueAnimator的setXxx()方法设置动画持续时间、插值方式、重复次数等。
- 调用ValueAnimator的start()方法启动动画。
- 为ValueAnimator注册AnimatorUpdateListener监听器,在该监听器中可以监听ValueAnimator计算出来的值的改变,并将这些值应用到指定对象上。
2.使用ObjectAnimator创建动画
使用ObjectAnimator有如下几个注意点:
- 要为该对象对应的属性提供setter方法;
- 调用ObjectAnimator的ofInt()、ofFloat()或ofObject()工厂方法时,如果values...参数只提供了一个值,那么这个值会被认为是结束值。该对象应该为该属性提供一个getter方法,这个getter方法的返回值将被作为开始值。
- 如果动画的对象时View,为了能显示动画效果,可能还需要在onAnimationUpdate()事件监听方法中调用View.invalidate()方法来刷新屏幕的显示。
1.使用属性动画
属性动画既可作用于UI组件,也可作用于普通的对象。定义属性动画有两种方式:
- 使用ValueAnimator或ObjectAnimator的静态工厂方法来创建动画。
- 使用资源文件来定义动画。
使用属性动画的步骤如下所示:
- 创建ValueAnimator或ObjectAnimator对象(既可从XML资源文件加载该动画资源,也可直接调用ValueAnimator或ObjectAnimator的静态工厂方法来创建动画)。
- 根据需要为Animator对象设置属性。
- 如果需要监听Animator的动画开始事件、动画结束事件、动画重复事件、动画值改变事件,并根据事件提供相应的处理代码,则应该为Animator对象设置事件监听器。
- 如果有多个动画需要按次序或同时播放,则应使用AnimatorSet组合这些动画。
- 调用Animator对象的start()方法启动动画。
使用SurfaceView实现动画
SurfaceView一般会与SurfaceHolder结合使用,SurfaceHolder用于向与之关联的SurfaceView上绘图,调用SurfaceView的getHolder()方法即可获取SurfaceView关联SurfaceHolder。
SurfaceHolder提供了如下方法来获取Canvas对象:
- Canvas lockCanvas():锁定整个SurfaceView对象,获取该SurfaceView上的Canvas。
- Canvas lockCanvas(Rect dirty):锁定SurfaceView上Rect划分的区域,获取该SurfaceView上的Canvas。