android中动画分为:属性动画,帧动画,layout动画。
1.属性动画
包含 位移,透明度,旋转等动画。属性动画简单点说就是通过修改控件的属性值来达到动画的效果。先看一下它的实现类:
/* This is the superclass for classes
*which provide basic support for animations which can be started, ended,
*and have AnimatorListeners added to them.
*/
public abstract class Animator implements Cloneable {
......
}
这个是所有动画的基类,里面包含了动画的mListener(),start(),cancel(),end(),......方法。
再看一下他的子类:
AnimatorSet
FakeAnimator
ObjectAnimator
RenderNodeAnimator
RevealAnimator
TimeAnimator
ValueAnimator
Android属性动画(注意最低兼容版本,不过可以使用开源项目来替代低版本问题)提供了以下属性:
- Duration:动画的持续时间;
- TimeInterpolation:定义动画变化速率的接口,所有插值器都必须实现此接口,如线性、非线性插值器;
- TypeEvaluator:用于定义属性值计算方式的接口,有int、float、color类型,根据属性的起始、结束值和插值一起计算出当前时间的属性值;
- Animation sets:动画集合,即可以同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟;
- Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响;
- Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以让此动画一直重复,或播放完时向反向播放;
接下来先来看官方为了解释原理给出的两幅图(其实就是初中物理题,不解释):
上面就是一个线性匀速动画,描述了一个Object的X属性运动动画,该对象的X坐标在40ms内从0移动到40,每10ms刷新一次,移动4次,每次移动为40/4=10pixel。
上面是一个非匀速动画,描述了一个Object的X属性运动动画,该对象的X坐标在40ms内从0移动到40,每10ms刷新一次,移动4次,但是速率不同,开始和结束的速度要比中间部分慢,即先加速后减速。
接下来我们来详细的看一下,属性动画系统的重要组成部分是如何计算动画值的,下图描述了如上面所示动画的实现作用过程。
其中的ValueAnimator是动画的执行类,跟踪了当前动画的执行时间和当前时间下的属性值;ValueAnimator封装了动画的TimeInterpolator时间插值器和一个TypeEvaluator类型估值,用于设置动画属性的值,就像上面图2非线性动画里,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。
为了执行一个动画,你需要创建一个ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用start后,整个动画过程中, ValueAnimator会根据已经完成的动画时间计算得到一个0到1之间的分数,代表该动画的已完成动画百分比。0表示0%,1表示100%,譬如上面图一线性匀速动画中总时间 t = 40 ms,t = 10 ms的时候是 0.25。
当ValueAnimator计算完已完成动画分数后,它会调用当前设置的TimeInterpolator,去计算得到一个interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。如上图2非线性动画中,因为动画的运动是缓慢加速的,它的插值分数大约是 0.15,小于t = 10ms时的已完成动画分数0.25。而在上图1中,这个插值分数一直和已完成动画分数是相同的。
当插值分数计算完成后,ValueAnimator会根据插值分数调用合适的 TypeEvaluator去计算运动中的属性值。
好了,现在我们来看下代码就明白这段话了,上面图2非线性动画里,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。所以这些类都是标准的API,我们来看下标准API就能类比自己写了,如下:
首先计算已完成动画时间分数(以10ms为例):t=10ms/40ms=0.25。
总结:属性动画就是 将属性的差值/时间/变化方式, 三者的关系得到某个时间点的属性值,然后赋值给view,view进行刷新。
来看一下使用,分为xml和java代码两种使用方式。
通过xml文件: activity_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
<scale
android:duration="1000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="0.0%"
android:pivotY="100.0%"
android:toXScale="0.0"
android:toYScale="1.0" />
<alph
......
/>
</set>
Animation animation = AnimationUtils.loadAnimation(this,
R.anim.activity_to_left);
vv.startAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
}
});
通过java代码实现
AnimationSet animationSet= new AnimationSet(true);
animationSet.setDuration(600);
animationSet.setInterpolator(new AccelerateInterpolator());
TranslateAnimation translateAnimation = new TranslateAnimation(
0, (float) (0.2 * width+0.2*w), 0, (float) (height - 0.8 * h+getActionBar().getHeight()));
animationSet.addAnimation(translateAnimation);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.8f,
1.0f, 0.8f, 1f, 1f);
animationSet.addAnimation(scaleAnimation);
animationSet.setFillAfter(true);
vv.startAnimation(animationSet);
再看一下有哪些属性
有这4大类
<alpha>
<scale>
<translate>
<rotate>
2.帧动画
zjun.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/progress_1" android:duration="200"/>
<item android:drawable="@drawable/progress_2" android:duration="200"/>
<item android:drawable="@drawable/progress_3" android:duration="200"/>
<item android:drawable="@drawable/progress_4" android:duration="200"/>
<item android:drawable="@drawable/progress_5" android:duration="200"/>
<item android:drawable="@drawable/progress_6" android:duration="200"/>
<item android:drawable="@drawable/progress_7" android:duration="200"/>
<item android:drawable="@drawable/progress_8" android:duration="200"/>
</animation-list>
android:oneshot="false" 是否循环
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@anim/zjun"
android:layout_gravity="center"/>
AnimationDrawable anim = (AnimationDrawable) iv.getBackground();
anim.start();
anim.stop();
原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。主要类是AnimationDrawable ,比较简单可参看http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.1_r1.2/android/graphics/drawable/AnimationDrawable.java#AnimationDrawabl
3.layout动画
layout动画在每次布局发生变化的时候系统调用的一个预加载动画效果,使用layout动画可以让布局的变化过度看起来更自然。使用起来很简单,只需在控件中添加一个属性就可以了,系统默认是不会启动layout动画的,因此我们平时的应用中不会产生这个效果。
当然,如果你想自定义一下这个动画效果,那就必须在代码中自己写了:新建一个LayoutTransition对象,调用setLayoutTransition()方法来为layout设置动画。
<LinearLayout android:id=
"@+id/container"
android:animateLayoutChanges=
"true"
...
/>
一般是添加,删除,隐藏时会看到效果。
最后在说一下使用动画时遇到的问题
1.给view添加了点击事件,当view移动后,点击原来的位置点击事件还会生效,而新位置不生效。
解决方案 http://www.68idc.cn/help/jiabenmake/qita/20141210139930.html
.。。。。。。。。
后续遇到再添加