说起动画,大家说有什么属性动画,播帧动画,补间动画。但是其中的区别没有很较真的了解过。既然阅读到了开发文档,就写个文章记录一下。
动画种类
Android 动画分为3种,
1属性动画 property animation,
2播帧动画frame animation,
3补间动画tween animation 。
涉及到的Java类
属性动画对应Animator, 通过改动类的对象(view对象)的属性值实现。
播帧动画对应AnimationDrawable, 播帧很简单了,就是一张张被设计好的图片连续刷,就是动画了。
补间动画对应Animation, 补间动画开发者只需指定动画开始,以及动画结束"关键帧", 而动画变化的"中间帧"则由系统计算并补齐。
属性动画 xml文件存放于animator文件夹中
可以通过XML文件来实现,存放于res/animator/目录下面。在指定的时间内可以修改一个目标对象的颜色,透明度,等等系列的属性。
XML语法如下
objectAnimator标签相关
<set //一个可以容纳其他标签的容器标签,它的里面可以放 objectAnimator 标签, valueAnimator标签或者set标签。其所对应的java类是 AnimatorSet
android:ordering=["together" | "sequentially"]> //设置动画执行顺序规则,together代表同一时间一起播放, sequantially代表按照子标签的顺序执行动画。
// objectAnimator是不可以直接写在XML中的,这样写是无效的。 我们必须通过 Animator类的 setAnimator()和 setTarget()才能确定一个view要表演什么动画。 最后必须要执行 start方法。动画才会执行。
<objectAnimator
android:propertyName="string" //属性名称,一个view的属性名称,例如alpha 或者 backgroundColor
android:duration="int" //动画经历的时长,以毫秒为单位
android:valueFrom="float | int | color" //动画最开始的属性对应值。
android:valueTo="float | int | color" //动画结束时属性对应值
android:startOffset="int" //在动画start之后的多长时间里 开启动画
android:repeatCount="int" //重复次数。 0位不重复, 1为重复一次, n 为重复n次。 -1 为无限重复。
android:repeatMode=["repeat" | "reverse"] //
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
我的例子
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="5000"
android:propertyName="alpha"
android:valueFrom="0f"
android:valueTo="1f"
android:repeatCount="-1"
android:startOffset="1000"
/>
</set>
animator相关标签
animator标签对应的类是 ValueAnimator。 上面的例子中也有关于animator的使用方法,它的每一个属性的含义与ObjectAnimator一致。看看以下的继承关系图:
可见其实ObjectAnimator是ValueAnimator的子类,说明ValueAnimator有的ObjectAnimator其实都有。用的时候甚至可以都用ObjectAnimator去处理!
**ObjectAnimator android:propertyName 的可能值是什么? **
1 translationX , translationY。 控制View的屏幕位置变化量,以layout容器的左上角为坐标原点
2 rotation, rotationX, rotationY, 用于控制2D旋转角度和围绕某枢轴点的3Dx旋转角度。
3 scaleX, scaleY , 控制着View围绕某枢轴点的2D缩放比例。
4 pivotX, pivotY,控制着枢轴点的位置,签署的旋转和缩放都是以此点为中心展开的,缺省的枢轴点是View对象的中心点。
5 x, y ,指View在容器内的最终位置,等于View左上角对于容器的坐标加上translationX, translationY后的值。
6 alpha,表示view的alpha透明度,缺省值为1不透明。 如果是0的话是完全透明。
通过自己敲代码: 需要注意的有以下几点
1 android:propertyName 不要乱写,一定是支持的值才好使
2 android:valueType 到底是哪种类型的一定要写对,写不对动画不出来。 比如你的propertyName是x, 但是valueType是intType是不对的,必须是浮点类型 floatType!!!
3 android:valueFrom 它的值一定不要带 dp px等杂七杂八的单位。纯数字!
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator
android:duration="3000"
android:propertyName="x"
android:valueType="floatType"
android:valueFrom="0"
android:valueTo="100"
android:repeatCount="0"
/>
<objectAnimator
android:duration="3000"
android:propertyName="y"
android:valueType="floatType"
android:valueFrom="0"
android:valueTo="100"
android:repeatCount="0"
/>
<objectAnimator
android:duration="5000"
android:propertyName="backgroundColor"
android:valueFrom="#FFFFFF"
android:valueTo="#FF0000"
android:repeatCount="0"
/>
</set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animator.property_animator);
set.setTarget(myObject);
set.start();
View animation(包括播帧动画和补间动画,两者都可以在XML文件中定义)
补间动画, 对应Java类为 Animation
是一种描述图片旋转,透明度变化,移动,拉伸的动画文件, 其XML文件存于anim文件夹中。
语法:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" // 此处的set标签对应AnimationSet类,
android:interpolator="@[package:]anim/interpolator_resource" //插值器 作用是把0到1的浮点映射到另一个浮点值变化上。例如先快后慢的动画, 自由落体式动画。
android:shareInterpolator=["true" | "false"] > //是否让子标签的动画共享这个插值器。
<alpha // 一个透明度变化的动画标签,对应的Java类是 AlphaAnimation
android:fromAlpha="float" //最初的不透明度
android:toAlpha="float" /> //最终的不透明度
<scale //一个改变view大小的动画。动画的大小改变是有一个中心点的。对应的是 pivotX, pivotY. java类为ScaleAnimation
android:fromXScale="float" //最初的大小比例, 1.0代表相对于原尺寸无变化
android:toXScale="float" //最终的大小比例, 1.0代表相对于原尺寸无变化
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float" //动画的大小改变是有一个中心点的。对应的是 pivotX, pivotY
android:pivotY="float" />
<translate //横向或者纵向运动,对应的Java类为 TranslateAnimation, 它的属性标签要么是 -100%~100%(以自己左上角为校准中心,相对于自身的宽高度移动 -100% 到 100% 的距离。) 要么是 -100%p~100%p(以自己坐上角为校准中心,移动其所在父容器的-100%~100%距离), 要么是纯float值(以自身的左上角为校准中心,移动float值代表的数量的像素点!)。
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate // 旋转动画 对应的java类是 RotateAnimation
android:fromDegrees="float" //开始的角度
android:toDegrees="float" //结束时的角度
android:pivotX="float" // 旋转中心,(相对于自身的点, 0, 0 代表左上角点 )像素 有 n%, n%p, n 这三种写法。含义和上面的一致
android:pivotY="float" /> // 旋转中心点,像素
<set>
...
</set>
</set>
我的例子
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:repeatMode="restart">
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100"
android:toYDelta="100"
/>
<rotate
android:fromDegrees="0.0"
android:toDegrees="180.0"
android:pivotX="50%p"
android:pivotY="50%p"
/>
</set>
ImageView image = (ImageView) findViewById(R.id.image);
Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
image.startAnimation(hyperspaceJump);
补间动画的插值器 (决定怎么运动)
作用,是可以用XML文件定义的,影响动画速度的一个工具。它可以使动画,加速,减速,重复,反弹,等等。上面有提到过,补间动画的set标签有一个属性,叫 android:interpolator, 其指的就是一个插值器。对应的java类为:Interpolator, 这个类有很多子类,每一个都可以表示特定的速度描述。
使用xml文件手写插值器。
从上面我们已经看出,系统已经为我们准备了一些很靠谱的插值器。但是有时候这些插值器不符合我们的需求,例如,我要一个加速度效果的插值器,加速度为9.0!!此时我们需要手动去写一个描述插值器的xml。语法如下
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute_name="value"
/>
语法解析:
InterpolatorName 是一个描述词,可以是上面插值器列表的任意一个插值器:如
<accelerateDecelerateInterpolator> //动画的开始和结束都会很慢,但是中间过程会有一个加速过程和减速过程
<accelerateInterpolator> //开始的时候很慢,但是后来依据加速度越来越快
<anticipateInterpolator> //开始的时候首先会向相反的方向移动一段距离,再回过去。
<anticipateOvershootInterpolator> //开始的时候会先向反方向执行一段距离,然后正常移动等到移动到尾部再向尾部的反向方移动一定距离。
<bounceInterpolator> //回弹,类似于一个物体自由落在地上又被弹回去一定距离又落下。
<cycleInterpolator> //来回循环,直至停止
<decelerateInterpolator> //减速,开始的时候很快,会按照一定的加速度越来越慢。
<linearInterpolator> // 匀速
<overshootInterpolator> // 省略
各个标签对应的属性
1 <accelerateDecelerateInterpolator> //动画的开始和结束都会很慢,但是中间过程会有一个加速过程和减速过程
没有属性
2 <accelerateInterpolator> //开始的时候很慢,但是后来依据加速度越来越快
android:factor 加速度,默认为1
3 <anticipateInterpolator> //开始的时候首先会向相反的方向移动一段距离,再回过去。
android:tension 紧绷关系,默认为2, 值越大,往反方向移动的距离会越大。
4 <anticipateOvershootInterpolator> //开始的时候会先向反方向执行一段距离,然后正常移动等到移动到尾部再向尾部的反向方移动一定距离。
android:tension:张力,默认为2, 值越大,往反方向移动的距离会越大。
android:extraTension :和 tension进行相乘,默认1.5 ,
5 <bounceInterpolator> //回弹,类似于一个物体自由落在地上又被弹回去一定距离又落下。
没有属性
6 <cycleInterpolator> //来回循环,直至停止
android:cycles 代表循环几次,默认1
7 <decelerateInterpolator> //减速,开始的时候很快,会按照一定的加速度越来越慢。
android:factor 加速度
8 <linearInterpolator> // 匀速
没有属性
9 <overshootInterpolator> // 省略
android:tension 张力
我的例子:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@anim/my_anticip">
<translate
android:fromXDelta="0%"
android:fromYDelta="0%p"
android:toXDelta="0%"
android:toYDelta="30%p" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<anticipateOvershootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="4"
android:extraTension="1.5">
</anticipateOvershootInterpolator>
播帧动画 对应的java类为AnimatorDrawable, xml文件存放于 drawable文件夹中
这个很容易理解,就是播放一组图片。其xml文件语法为:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" //这个标签必须是根标签
android:oneshot=["true" | "false"] > //是否播放一次, true是播放一次, false是循环播放
<item
android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer" /> //当前图片播放的时间
</animation-list>
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = rocketImage.getBackground();
if (rocketAnimation instanceof Animatable) {
((Animatable)rocketAnimation).start();
}