帧动画
首先介绍最简单的帧动画,帧动画就是顺序的播放一系列的图片,从而产生动画效果。
下面是一个的xml文件中配置的帧动画的通用格式示例:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["false"|"true"]
android:variablePadding=["false"|"true"]
android:visible=["false"|"true"] >
<!--android:oneshot="true" oneshot取值为false表示重复播放动画,取值为true表示只播放一次 -->
<!--android:visible 参数为布尔值,设置AnimationDrawable的可见性,true可见,false不可见,-->
<!--xml中定义的visible属性无用,因为根本没有解析。-->
<!--android:variablePadding 表示是否支持可变的Padding。-->
<!--false表示使用所有帧中最大的Padding,true表示使用当前帧的padding。-->
<item android:drawable="@drawable/具体资源名称" android:duration="integer"/> <!--duration表示动画的执行时间-->
<item android:drawable="@drawable/具体资源名称" android:duration="integer"/>
<item android:drawable="@drawable/具体资源名称" android:duration="integer"/>
//可以有多个item,也可以只有一个,整个动画的执行时间是所有item的duration时间的总和
</animation-list>
下面给出一个具体的实例,在drawable文件夹下创建一个名为frame_animation_test.xml的文件,文件中的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"
android:variablePadding="true">
<!--android:oneshot="true" oneshot取值为false表示重复播放动画,取值为true表示只播放一次 -->
<!--android:visible 参数为布尔值,设置AnimationDrawable的可见性,true可见,false不可见,-->
<!--xml中定义的visible属性无用,因为根本没有解析。-->
<!--android:variablePadding 表示是否支持可变的Padding。-->
<!--false表示使用所有帧中最大的Padding,true表示使用当前帧的padding。-->
<item android:drawable="@drawable/test4" android:duration="1000"/> <!--duration表示动画的执行时间-->
<item android:drawable="@drawable/test3" android:duration="1000"/>
<item android:drawable="@drawable/test2" android:duration="1000"/>
<item android:drawable="@drawable/test1" android:duration="1000"/>
<item android:drawable="@drawable/test0" android:duration="1000"/>
<!--此时外层item的drawable为colorPrimary,-->
<!--相当于外层item从内层aniamtion-list的子元素内找到一个drawable用做自己的drawable-->
<!--内层animation-list中的子元素的时间是无效的,外层item只会使用自己设置的时间-->
<item android:duration= "3100">
<animation-list >
<item android:drawable="@color/colorPrimary" android:duration="500"/>
<item android:drawable="@color/c_f034f9" android:duration="500"/>
</animation-list >
</item>
<!--这种方式定义,是无法解析的,会报异常-->
<!--<item android:drawable="@color/c_00c8aa">-->
<!--<animation-list >-->
<!--<item android:drawable="@color/black_deep" android:duration="500"/>-->
<!--<item android:drawable="@color/c_fc5348" android:duration="500"/>-->
<!--</animation-list >-->
<!--</item>-->
<!--下面这种方式定义的item,里面的animation-list就没有任何作用-->
<item android:drawable="@color/c_fea116" android:duration= "800">
<animation-list >
<item android:drawable="@color/c_ddff90" android:duration="500"/>
<item android:drawable="@color/colorPrimaryDark" android:duration="500"/>
</animation-list >
</item>
<!--不会执行-->
<animation-list >
<item android:drawable="@color/black_deep" android:duration="500"/>
<item android:drawable="@color/c_00c8aa" android:duration="500"/>
</animation-list >
</animation-list>
配置完帧动画后,就可以在代码中启动动画了。
TextView iv_frame_animation = (TextView) findViewById(R.id.iv_frame_animation);
iv_frame_animation.setBackgroundResource(R.drawable.frame_animation_test);
AnimationDrawable animation = (AnimationDrawable) iv_frame_animation.getBackground();
animation.start();
以上这种方式,是通过xml配置动画。当然还可以直接通过代码来配置帧动画。
animation-list 标签对应的类是AnimationDrawable。下面的实例是通过代码直接创建帧动画:
AnimationDrawable animationDrawable = createAnimationDrawableByCode();
ImageView iv = findViewById(R.id.iv);
iv.setBackgroundDrawable(animationDrawable);
animationDrawable.start();//注意这里一定要start,否则,动画是不会执行的
public AnimationDrawable createAnimationDrawableByCode(){
AnimationDrawable animationDrawable = new AnimationDrawable();
animationDrawable.addFrame(getResources().getDrawable(R.color.colorPrimaryDark),1000);
animationDrawable.addFrame(getResources().getDrawable(R.color.red),1000);
animationDrawable.addFrame(getResources().getDrawable(R.color.c_00c8aa),1000);
animationDrawable.addFrame(getResources().getDrawable(R.color.accent),1000);
animationDrawable.addFrame(getResources().getDrawable(R.color.c_ddff90),500);
animationDrawable.setOneShot(false);
return animationDrawable;
}
还有一点要特别注意:
当同一个animationDrawable设置到多个不同的view上时,只有最后一个view才执行动画效果。下面的示例中,只有tv_frame_animation_2这个控件执行动画效果,iv_3这个控件不执行动画。
AnimationDrawable animationDrawable2 = createAnimationDrawableByCode();
ImageView iv_3 = findViewById(R.id.iv_3);
iv_3.setImageDrawable(animationDrawable2);
animationDrawable2.start();
TextView tv_frame_animation_2 = findViewById(R.id.tv_frame_animation_2);
tv_frame_animation_2.setBackgroundDrawable(animationDrawable2);
animationDrawable2.start();
由于帧动画中使用的图片比较多,如果图片所在的内存过大,会导致oom,所以,使用时,要注意,尽量少用占用内存过大的图片。
Tween动画
Tween动画,也称为补间动画。补间动画也分四种,分别是平移动画(Translation),缩放动画(Scale),透明度动画(Alpha),选择动画(Rotation)。下面先介绍下,补间动画的通用配置格式:
<?xml version="1.0" encoding="utf-8"?>
<!--通用的属性:-->
<!--android:duration:设置动画持续时间-->
<!--android:repeatMode:设置动画重复模式,restart 表示,重头开始,reverse 表示从结尾在到开头-->
<!--android:fillAfter:如果fillAfter设为true,则动画执行后,控件将停留在动画结束的状态-->
<!--android:fillBefore:如果fillBefore设为true,则动画执行后,控件将回到动画开始的状态-->
<!--android:startOffset(long startOffset):设置动画执行之前等待的时间(单位:毫秒)-->
<!--android:repeatCount(int repeatCount):设置动画重复的次数 ,这里设置无效-->
<!--android:shareInterpolator:如果取值true,表示所有的子动画都共享同一个插值器,如果取值false,则子动画不共享插值器-->
<!--android:interpolator:设置动画的变化速度,其值: {-->
<!--android:interpolator="@android:anim/accelerate_decelerate_interpolator":先加速,后减速-->
<!---->
<!--android:interpolator="@android:anim/accelerate_interpolator":加速-->
<!---->
<!--android:interpolator="@android:anim/decelerate_interpolator":减速-->
<!---->
<!--android:interpolator="@android:anim/cycle_Interpolator":动画循环播放特定次数,速率改变沿着正弦曲线-->
<!---->
<!--android:interpolator="@android:anim/linear_Interpolator":匀速-->
<!--}-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="integer"
android:fillAfter=["false"|"true"]
android:repeatMode=["restart"|"reverse"]
android:startOffset="integer"
android:shareInterpolator=["false"|"true"]>
<!--fromAlpha属性为动画起始时透明度-->
<!--toAlpha 属性为动画结束时透明度-->
<!--0.0表示完全透明,1.0表示完全不透明,以上值取0.0-1.0之间的float数据类型的数字。-->
<alpha android:fromAlpha="float"
android:toAlpha="float">
</alpha>
<!--fromDegrees 为动画起始时物件的角度 说明-->
<!--toDegrees 属性为动画结束时物件旋转的角度 可以大于360度-->
<!--当角度为负数——表示逆时针旋转-->
<!--当角度为正数——表示顺时针旋转-->
<!--(负数from——to正数:顺时针旋转)-->
<!--(负数from——to负数:逆时针旋转)-->
<!--(正数from——to正数:顺时针旋转)-->
<!--(正数from——to负数:逆时针旋转)-->
<!--pivotX pivotY 为动画相对于物件的X、Y坐标的开始位-->
<!--属性值说明:-->
<!--pivotX取值,50表示使用绝对位置-->
<!--pivotX取值,50%表示相对于控件本身的位置-->
<!--pivotX取值,50%p表示相对于父控件本身的位置-->
<rotate android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float">
</rotate>
<!--fromXScale[float] fromYScale[float] 为动画起始时,X、Y坐标上的伸缩尺寸-->
<!--toXScale [float] toYScale[float] 为动画结束时,X、Y坐标上的伸缩尺寸-->
<!--0.0表示收缩到没有,1.0表示正常无伸缩,值小于1.0表示收缩,值大于1.0表示放大-->
<!--pivotX[float] pivotY[float] 为动画相对于物件的X、Y坐标的开始位置-->
<!--属性值说明:-->
<!--pivotX取值,50表示使用绝对位置-->
<!--pivotX取值,50%表示相对于控件本身的位置-->
<!--pivotX取值,50%p表示相对于父控件本身的位置-->
<scale android:pivotX="float"
android:pivotY="float"
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float">
</scale>
<!--fromXDelta toXDelta 为动画、结束起始时 X坐标上的位置-->
<!--fromYDelta toYDelta 为动画、结束起始时 Y坐标上的位置-->
<translate android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float">
</translate>
</set>
当然,也可以在xml文件中,使用 , ,,作为根节点,来使用单个的动画。平时项目中使用,建议还是用set标签作为根节点,在set标签下,添加自己想要的动画。在xml文件中,配置完补间动画后,就可以在代码中去启动动画了。下面给出一个具体是演示示例,在anim目录下,新建animation_test.xml文件,文件中的具体配置信息如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="false"
android:repeatMode="restart"
android:startOffset="500"
android:shareInterpolator="true">
<alpha android:fromAlpha="0"
android:toAlpha="1"
android:repeatCount="3">
</alpha>
<rotate android:fromDegrees="0"
android:toDegrees="60"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="3">
</rotate>
<scale android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="1.0"
android:toXScale="0.5"
android:fromYScale="1.0"
android:toYScale="0.5"
android:repeatCount="3">
</scale>
<translate android:fromXDelta="0"
android:toXDelta="50"
android:fromYDelta="0"
android:toYDelta="50"
android:repeatCount="3">
</translate>
</set>
接着在代码中使用:
ImageView iv_view_animation = (ImageView) findViewById(R.id.iv_view_animation);
//通过AnimationUtils类加载xml文件中配置的动画信息
Animation animation = AnimationUtils.loadAnimation(this,R.anim.translate_anim);
//设置动画的总时间
animation.setDuration(5000);
//设置重复3次,注意,这里的重复3次,最终是会执行4次,第一次执行完后,onAnimationRepeat方法不会执行,后面3次才会回调这个方法
animation.setRepeatCount(3);
//启动动画
iv_view_animation.startAnimation(animation);
//给动画设置监听
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始了,可以添加开始的逻辑
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束了,可以添加结束的逻辑
}
@Override
public void onAnimationRepeat(Animation animation) {
//重复动画
}
});
在xml文件中配置的补间动画中,
set 标签其实 对应的是 AnimationSet类,
alpha 标签对应的是AlphaAnimation类,
rotate 标签对应的是 RotateAnimation类,
scale标签对应的是 ScaleAnimation,
所以,我们不仅可以通过xml文件来配置动画,还可以通过代码来创建动画。
下面的示例是通过代码来创建动画完成相同的效果:
ImageView iv_view_animation2 = findViewById(R.id.iv_view_animation2);
AnimationSet animationSet = createAnimationByCode();
iv_view_animation2.setAnimation(animationSet);
animationSet.start();
private AnimationSet createAnimationByCode() {
//构造方法传入true,表示所有的子动画都共享插值器
AnimationSet animationSet = new AnimationSet(true);
//设置中的动画时间是5秒
animationSet.setDuration(5000);
//重复执行3次
//animationSet.setRepeatCount(3);//这里设置无效
//设置动画执行完后,不停留在最后动画结束的状态
animationSet.setFillAfter(false);
//设置动画的重复模式是,下次重复是,从头开始
animationSet.setRepeatMode(AnimationSet.RESTART);
//设置动画开始时等待500毫秒
animationSet.setStartOffset(500);
//创建alpha动画,透明度重0,变到1,即重完全透明到完全不透明
AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
RotateAnimation rotateAnimation = new RotateAnimation(0f, 60, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f,0.5f,1.0f,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
TranslateAnimation translateAnimation = new TranslateAnimation(0f,50f,0,50f);
//如果要设置重复次数,需要对每个子动画进行设置,给animationSet设置重复次数是无效的
alphaAnimation.setRepeatCount(3);
rotateAnimation.setRepeatCount(3);
scaleAnimation.setRepeatCount(3);
translateAnimation.setRepeatCount(3);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(translateAnimation);
return animationSet;
}