android的动画一共分为三种,分别是逐帧动画,补间动画,属性动画。逐帧动画,就是将一系列的图片,定义好之后,每一张图片就是一帧,在快速播放的条件下就产生了动画的效果。补间动画就是定义动画的初始位置,或者初始透明度。和最终的为位置和透明度,系统会自动补齐中间的部分。补间动画主要又有四种分类,透明度渐变动画AlphaAnimation,旋转动画RotateAnimation,平移动画TranslateAnimation,伸缩动画ScaleAnimation。这里强调一点这里的所有动画都是只能针对view组件才会生效的,android3.0之后引入了属性动画,弥补了以前动画的不足之处,让任何对象都可以运用动画。
这个动画的制作比较简单,首先需要找到很多张图片,将这些图片放置在drawable目录下,同时在在drawable 下定义一个xml,例如anim.xml文件,引用drawable下的所有图片
然后在activity_main目录中将背景设置为
android:background="@drawable/anim"
调用动画的代码为:
LinearLayout linearLayout=(linearLayout)findviewById(R.layout.myLinearLayout);
AnimationDrawable anim=(AnimationDrawable)linearLayout.getBackground();
anim.start();
首先除了逐帧动画之外,补间动画定义的xml文件必须位于,anim目录下面,一般情况下默认的android studio的res目录下面是没有这个目录的,这个目录需要我们去直接定义。这个时候你也许会问,那如果要是逐帧动画的资源文件是不是也可以放在这个目录下面呢?在我的android studio中,如果我将逐帧动画的资源放在anim目录下就会报错,编译器会提醒我将资源放在drawable目录下。
首先来定义动画的xml文件
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="2000"//设置动画的持续时间,单位是毫秒
android:fromAlpha="1"//设置初始的透明度
android:repeatCount="1"//动画的重复次数
android:repeatMode="reverse"//动画的重复模式
android:toAlpha="0">//动画结束时的透明度
alpha>
set>
这里使用的属性是相当少的,也是最主要的几个属性,其他的属性可以参考官方的api
同理定义动画的xml文件,将xml文件放在anim目录下
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="2000"//设置动画的持续时间,单位是毫秒
android:fromDegrees="0"//设置动画开始的旋转角度
android:interpolator="@android:anim/accelerate_interpolator"//旋转的加速器,这里表示开始的时候比较慢,后来慢慢加速。
android:pivotX="50%"//开始的x坐标
android:pivotY="50%"//开始的Y坐标
android:toDegrees="720">//结束时的角度
</rotate>
</set>
同上,定义xml文件,放置在anim目录下
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1"//水平方向的缩放系数,1表示没有变化和原图一样
android:fromYScale="1"//竖直方向的缩放系数,1表示没有变化和原图一样
android:toXScale="2.0"//水平方向的缩放系数,2变为原来的2倍
android:toYScale="2.0"
android:pivotY="50%"//制定轴心得Y坐标,这里表示为图像的中心
android:pivotX="50%"
android:repeatMode="reverse"
android:repeatCount="1"
android:duration="2000"
>
scale>
set>
同上
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:repeatCount="1"//重复的次数
android:duration="2000"//动画持续的时间
android:fromXDelta="0"//动画开始的x坐标
android:fromYDelta="0"//动画开始的Y坐标
android:repeatMode="reverse"//动画的重复模式
android:toXDelta="860"//结束时动画的x坐标
android:toYDelta="0">
translate>
set>
通过上面四种动画的xml文件,其实可以看得出来很多动画的属性都是相同之处的,接下来我怎么启动动画呢?首先我们需要加载不同的动画资源,代码如下。
rotate= AnimationUtils.loadAnimation(this,R.anim.anim_roate);
translate= AnimationUtils.loadAnimation(this,R.anim.anim_translate);
scale= AnimationUtils.loadAnimation(this,R.anim.anim_scale);
alpha= AnimationUtils.loadAnimation(this,R.anim.anim_alpha);
找到需要实现动画效果的view,开始动画
imageView=(ImageView)findViewById(R.id.imageView);
imageView.startAnimation(rotate);//其他的动画效果类似
这个动画是目前主流的动画用法,就连官方的文档上面都推荐,使用动画第一最好使用属性动画。属性动画,可以使用xml文件实现,也可以直接使用代码实现,我们先来看一下官方的xml实现,以下内容来之于android.develop与补间动画和逐帧动画不同,我们需要重新再res目录下面定义一个animator目录,然后将定义的xml文件放在该目录下面
<set xmlns:android="http://schemas.android.com/apk/res/android">
<set>
<objectAnimator android:duration="500"
android:propertyName="x"
android:valueTo="400"
android:valueType="intType">
objectAnimator>
<objectAnimator android:duration="500"
android:propertyName="y"
android:valueTo="300"
android:valueType="intType">
objectAnimator>
<objectAnimator android:propertyName="alpha"
android:duration="500"
android:valueTo="1f">
objectAnimator>
set>
set>
在MainActivity的onCreate()方法中直接调用下面的代码。实现动画
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(MainActivity.this,
R.animator.animatortest);
set.setTarget(imageView);
set.start();
当然不适用xml文件的方式,也很方便甚至代码更加简洁一点,例如,要实现在y轴上面先变为原来的两倍,在变回原来的样子,用代码实现如下,“scaleY”是动画的属性们在这个地方,我们可以定义为透明度的alpha 平移的translate,除此之外也可以自己定义新的属性。
ObjectAnimator animator = ObjectAnimator.ofFloat(imagView, "scaleY", 1f, 2f, 1f);
animator.setDuration(5000);
animator.start();
AnimatorSet这个类主要是用来实现组合动画效果的,该类提供了四个方法
ObjectAnimator提供的方法,有ofFloat(),ofInt(),这里介绍一个方法ofObject(),查看底层的ofObject()的源码
/**
* Constructs and returns a ValueAnimator that animates between Object values. A single
* value implies that that value is the one being animated to. However, this is not typically
* useful in a ValueAnimator object because there is no way for the object to determine the
* starting value for the animation (unlike ObjectAnimator, which can derive that value
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
* Note: The Object values are stored as references to the original
* objects, which means that changes to those objects after this method is called will
* affect the values on the animator. If the objects will be mutated externally after
* this method is called, callers should pass a copy of those objects instead.
*
*
Since ValueAnimator does not know how to animate between arbitrary Objects, this
* factory method also takes a TypeEvaluator object that the ValueAnimator will use
* to perform that interpolation.
*
* @param evaluator A TypeEvaluator that will be called on each animation frame to
* provide the ncessry interpolation between the Object values to derive the animated
* value.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
*/
public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
ValueAnimator anim = new ValueAnimator();
anim.setObjectValues(values);
anim.setEvaluator(evaluator);
return anim;
}
我们来看参数说明:
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
*/
在点击进去查看TypeEvaluator 发现这个只是一个接口里面定义的方法为
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction
representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (x1 - x0)
,
* where x0
is startValue
, x1
is endValue
,
* and t
is fraction
.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
根据参数的说明大概的意识,这个接口里面的方法定义了从动画开始到动画结束时每一个时刻的动画所处的值,也就是说我们如果要定义属于自己的的ofObject()方法就必须要实现这个接口,重写里面的evaluate()方法,并把这个接口传递给你的ofObject()方法。再回到ofObject的第二个参数Object… values,这是一个可变的参数,可以定义你要实现动画的对象的一系列轨迹之类的。接下来案例的实现就先暂时放一放