欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android动画解析(一)-----逐帧动画和补间动画

程序员文章站 2022-03-25 14:56:49
...

今天项目又用到了动画,发现之前掌握的那些又遗忘了不少,趁着有时间,再重新捋顺一边。

Android中的动画分为 逐帧动画,补间动画,属性动画 三种.

逐帧动画(Frame Animation)

逐帧动画:就像GIF图片一样,通过一系列的Drawable依次显示来模拟动画效果。

  • 使用方式:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/pic1" android:duration="150" />
    <item android:drawable="@drawable/pic2" android:duration="150" />
    <item android:drawable="@drawable/pic3" android:duration="150" />
</animation-list>

<!--XML文件以<animation-list>为根元素,
以<item>表示要轮换显示的图片,
oneshot属性,用于设置播放模式(是单次播放还是循环播放)
duration属性表示各项显示的时间。
XML文件要放在/res/drawable/目录下-->
  • 调用方法:
 AnimationDrawable animationDrawable = (AnimationDrawable) loadingImage.getDrawable();
 animationDrawable.start();//开始动画
 animationDrawable.stop();//结束动画

补间动画(Tween Animation)

补间动画:给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
补间动画是使用Animation类创建的,下面的列表说明了四种可用的动画类型:

动画类型 简介
AlphaAnimation 可以改变View的透明度。(透明度渐变动画)
ScaleAnimation 允许缩放选中的View。(缩放动画)
RotateAnimation 可以在XY平面上旋转选中的View。(旋转动画)
TranslateAnimation 可以在屏幕上移动选中的View。(平移动画)

当View设置补件动画后,动画只是移动了内容,View本身其实还在原地,所以点击事件也还是在原地,如果想让点击事件跟着移动,最简单的是使用属性动画。

TranslateAnimation(平移动画)

java代码写法
TranslateAnimation 
animation = new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);

// fromXDelta 属性为动画起始时 X坐标上的位置    toXDelta   属性为动画结束时 X坐标上的位置
// fromYDelta 属性为动画起始时 Y坐标上的位置    toYDelta   属性为动画结束时 Y坐标上的位置
//  没有指定fromXType toXType fromYType toYType 时候, 默认是以自己为相对参照物       

...
View.startAnimation(animation);
XML文件写法

通过配置XML文件来实现平移动画,文件需要放在res\anim目录中,在动画文件中通过<translate>标签设置移动效果。首先在res\anim目录下建一个动画文件

translate_tween.xml,该文件的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"  
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/accelerate_interpolator"   
    android:toXDelta="60"
    android:toYDelta="60" >

</translate>
<!-- android:interpolator     动画差值器-->
<!-- android:duration        动画持续时间,以毫秒为单位 -->
<!-- android:fillAfter       如果设置为true,控件动画结束时,将保持动画最后时的状态-->
<!-- android:fillBefore      如果设置为true,控件动画结束时,还原到开始动画前的状态-->
<!-- android:fillEnabled     与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态-->
<!-- android:repeatCount     重复次数-->
<!-- android:repeatMode      重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。-->
// 在代码中这样调用
Animation animation=AnimationUtils.loadAnimation(this, R.anim.translate_tween);
View.startAnimation(animation);

或者用这种方式
//View.setAnimation(animation);
//animation.start();
TranslateAnimation特有属性

 * android:fromXDelta="0%"   动画开始执行时X轴方向控件的起始位置,
                    * 当value加%时(例如80%),意思是相对于控件的原始位置往右的80%控件宽度的位置  
                    * 又例如value为-20%时,意思是相对于控件的原始位置往左的20%控件宽度的位置。
                    * 当Value不加%时(例如80),表示相对于控件的原始位置往右80个像素(px)的位置,
                    * 又如当Value为-20时,即往左20个像素。  

* android:toXDelta="100%"动画结束执行时X轴方向控件的结束位置,Value可以加%,也可以不加%,原理同上  
* android:fromYDelta="0%"动画开始执行时Y轴方向控件的起始位置,Value可以加%,也可以不加%,原理同上  
* android:toYDelta="100%"动画结束执行时Y轴方向控件的结束位置,Value可以加%,也可以不加%,原理同上  

AlphaAnimation(透明度渐变动画)

Java代码写法
 AlphaAnimation mAlphaAnimation = new AlphaAnimation(float fromAlpha, float toAlpha);
 //fromAlpha:设置动画开始时控件的透明度
  //toAlpha:设置动画结束时的控件的透明度 
  //两个值取值都为0~1之间,0.0为透明,控件不显示,1.0为不透明,控件全部显示 
  ...
  View.startAnimation(mAlphaAnimation);
XML写法

同样文件需要放在res\anim目录中,在动画文件中通过<alpha>标签设置渐变效果。首先在res\anim目录下建一个动画文件
alpha_tween.xml,该文件的内容如下:

<alpha xmlns:android="http://schemas.android.com/apk/res/android"  
        android:fromAlpha= "0.0"  
        android:toAlpha= "1.0"  
        >  
</alpha>  
<!-- android:interpolator     动画差值器-->
<!-- android:duration        动画持续时间,以毫秒为单位 -->
<!-- android:fillAfter       如果设置为true,控件动画结束时,将保持动画最后时的状态-->
<!-- android:fillBefore      如果设置为true,控件动画结束时,还原到开始动画前的状态-->
<!-- android:fillEnabled     与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态-->
<!-- android:repeatCount     重复次数-->
<!-- android:repeatMode      重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。-->
// 在代码中这样调用
Animation animation=AnimationUtils.loadAnimation(this, R.anim.alpha_tween);
View.startAnimation(animation);

或者用这种方式
//View.setAnimation(animation);
//animation.start();
AlphaAnimation特有属性
android:fromAlpha:动画开始时的透明度,变化范围为0.0-1.0,0.0表示完全透明,1.0表示完全不透明
android:toAlpha:动画结束是的透明度,变化范围和意义同上。

RotateAnimation(旋转动画)

Java代码写法
RotateAnimation mRotateAnimation =  new RotateAnimation(float fromDegrees, float toDegrees,  
             int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);

// android:fromDegrees :动画开始时旋转的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
//android:toDegrees : 动画结束时旋转到的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数

//android:pivotXType: 确定动画在X轴的中心位置类型。与下面的pivotXValue结合,确定X轴上旋转中心。(取值见下表)

//android:pivotXValue  :旋转点X轴坐标值,float类型,可以是数值、百分数、百分数p三种样式,比如50、50%、50%p
                        //当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标,
                        //如果是50%;表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;
                        //如果是50%p,那么就是表示在当前控件的左上角加上父控件宽度的50%做为旋转点X坐标。

//android:pivotYType: 确定动画在Y轴的中心位置类型。取值及意义跟android:pivotXType一样。
//android:pivotYValue:旋转点Y轴坐标值,取值及意义跟android:pivotX一样。

...
View.startAnimation(mRotateAnimation);
pivotXType值 效果
Animation.ABSOLUTE 默认值,围绕设置动画控件的左上角旋转与pivotXValue = 0,pivotYVaule = 0效果相同
Animation.RELATIVE_TO_PARENT 设置动画控件的左上角为坐标原点(0,0),动画旋转轴的坐标为(parent.getWidth*pivotXValue,parent.getHeight*pivotYValue)[parent为view的父控件]负数向左(X轴)/上(Y轴)偏移,正数向右(X轴)/下(Y轴)偏移;
Animation.RELATIVE_TO_SELF 设置动画控件的左上角为坐标原点(0,0),动画旋转轴的坐标为(view.getWidth*pivotXValue,view.getHeight*pivotYValue)负数向左(X轴)/上(Y轴)偏移,正数向右(X轴)/下(Y轴)偏移;
XML文件写法

在res\anim目录下建一个动画文件rotate_tween.xml,该文件的内容如下:

    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             >  
    </rotate>  
<!-- android:interpolator=     动画差值器-->
<!-- android:duration        动画持续时间,以毫秒为单位 -->
<!-- android:fillAfter       如果设置为true,控件动画结束时,将保持动画最后时的状态-->
<!-- android:fillBefore      如果设置为true,控件动画结束时,还原到开始动画前的状态-->
<!-- android:fillEnabled     与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态-->
<!-- android:repeatCount     重复次数-->
<!-- android:repeatMode      重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。-->
// 在代码中这样调用
Animation animation=AnimationUtils.loadAnimation(this, R.anim.rotate_tween);
View.startAnimation(animation);

或者用这种方式
//View.setAnimation(animation);
//animation.start();
RotateAnimation特有属性
android:fromDegrees:动画开始时旋转的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
android:toDegrees: 动画结束时旋转到的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
android:pivotX:旋转点X轴坐标,float类型,可以是数值、百分数、百分数p三种样式,比如5050%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标,如果是50%;表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;如果是50%p,那么就是表示在当前控件的左上角加上父控件宽度的50%做为旋转点X坐标。
android:pivotY:旋转点Y轴坐标,取值及意义跟android:pivotX一样。

ScaleAnimation(缩放动画)

Java代码写法
ScaleAnimation mScaleAnimation = ScaleAnimation(float fromX, float toX, float fromY,  
        float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);
// float fromX 动画起始时 X坐标上的伸缩尺寸 比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍
// float toX 动画结束时 X坐标上的伸缩尺寸   
// float fromY 动画起始时Y坐标上的伸缩尺寸   
// float toY 动画结束时Y坐标上的伸缩尺寸   

//android:pivotXType: 确定动画在X轴的中心位置类型。与下面的pivotXValue结合,确定X轴上缩放中心点。。(取值见下表)
// float pivotXValue 动画相对于物件的X坐标的开始位置   
// int pivotYType 动画在Y轴相对于物件位置类型   
// float pivotYValue 动画相对于物件的Y坐标的开始位置   

...
View.startAnimation(mScaleAnimation);
pivotXType值 效果
Animation.ABSOLUTE 默认值,设置动画控件从左上角缩放,与pivotXValue = 0,pivotYVaule = 0效果相同
Animation.RELATIVE_TO_PARENT 设置动画控件的左上角为坐标原点(0,0),动画缩放点的坐标为(parent.getWidth*pivotXValue,parent.getHeight*pivotYValue)【parent为view的父控件】负数向左(X轴)/上(Y轴)偏移,正数向右(X轴)/下(Y轴)偏移;
Animation.RELATIVE_TO_SELF 设置动画控件的左上角为坐标原点(0,0),动画所放点的坐标为(view.getWidth*pivotXValue,view.getHeight*pivotYValue)负数向左(X轴)/上(Y轴)偏移,正数向右(X轴)/下(Y轴)偏移;
XML文件写法
<?xml version="1.0" encoding= "utf-8"?>   
<scale xmlns:android="http://schemas.android.com/apk/res/android"  
       android:fromXScale= "2.0"  
       android:toXScale= "1.0"  
       android:fromYScale= "2.0"  
       android:toYScale= "1.0"  
       android:pivotX= "50%"  
       android:pivotY= "50%"  
       >  
</scale> 
<!-- android:interpolator=     动画差值器-->
<!-- android:duration        动画持续时间,以毫秒为单位 -->
<!-- android:fillAfter       如果设置为true,控件动画结束时,将保持动画最后时的状态-->
<!-- android:fillBefore      如果设置为true,控件动画结束时,还原到开始动画前的状态-->
<!-- android:fillEnabled     与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态-->
<!-- android:repeatCount     重复次数-->
<!-- android:repeatMode      重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。-->
// 在代码中这样调用
Animation animation=AnimationUtils.loadAnimation(this, R.anim.rotate_tween);
View.startAnimation(animation);

或者用这种方式
//View.setAnimation(animation);
//animation.start();
ScaleAnimation特有属性
android:fromXScale起始的X方向上相对自身的缩放比例,类型float,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍
android:toXScale:结尾的X方向上相对自身的缩放比例,类型float
android:fromYScale:起始的Y方向上相对自身的缩放比例,类型float
android:toYScale:结尾的Y方向上相对自身的缩放比例,类型float
android:pivotX: 缩放起点X轴坐标,可以是数值、百分数、百分数p ,具体意义roate中已经演示
android:pivotY:缩放起点Y轴坐标,取值及意义与pivotX一样

补间动画设置动画监听事件

mAnimation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                //在动画开始时执行处理
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //在动画重复时执行处理
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //在动画完成后执行处理
            }
        });

AnimationSet

AnimationSet 可以让许多个动画在同一时间开始(也就是动画的叠加)
注意 : AnimationSet 和 AnimatorSet 注意区分区别,这里只做AnimationSet讲解。下篇博客讲解AnimatorSet

Java 代码写法
    //创建动画,参数表示他的子动画是否共用一个插值器
        AnimationSet animationSet = new AnimationSet(true);
        //添加动画(可以添加多个,每个动画都可以单独设置属性)
        animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
        animationSet.addAnimation(new TranslateAnimation(0,120 , 0, -300));

        //设置插值器
        animationSet.setInterpolator(new LinearInterpolator());
        //设置动画持续时长
        animationSet.setDuration(3000);
        //设置动画结束之后是否保持动画的目标状态
        animationSet.setFillAfter(true);
        //设置动画结束之后是否保持动画开始时的状态
        animationSet.setFillBefore(false);
        //设置重复模式
        animationSet.setRepeatMode(Animation.REVERSE);
        //设置重复次数
        animationSet.setRepeatCount(Animation.INFINITE);
        //设置动画延时时间
        animationSet.setStartOffset(2000);
        //取消动画
        animationSet.cancel();
        //释放资源
        animationSet.reset();
        //开始动画
        mIvImg.startAnimation(animationSet);
XML文件写法

文件目录:res/anim/animation_set.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:shareInterpolator="true">
    <alpha
        android:duration="2000"
        android:fillAfter="true"
        android:fillBefore="false"
        android:fromAlpha="1.0"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toAlpha="0.0"/>
    <rotate
        android:duration="2000"
        android:fillAfter="true"
        android:fillBefore="false"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toDegrees="360"/>
    <set
        android:interpolator="@android:anim/bounce_interpolator"
        android:shareInterpolator="true"
        android:startOffset="1000">
        <scale
            android:duration="2000"
            android:fillAfter="true"
            android:fillBefore="false"
            android:fromXScale="1.0"
            android:fromYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatCount="-1"
            android:repeatMode="reverse"
            android:toXScale="2.0"
            android:toYScale="2.0"/>
        <translate
            android:duration="2000"
            android:fillAfter="true"
            android:fillBefore="false"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:repeatCount="-1"
            android:repeatMode="reverse"
            android:toXDelta="200%"
            android:toYDelta="200%"/>
    </set>
</set>
Java代码中调用  
 AnimationSet animationSet = (AnimationSet)  
                AnimationUtils.loadAnimation(XmlViewAnimationActivity.this, R.anim.animation_set);
 View.startAnimation(animationSet);

差值器效果

AccelerateDecelerateInterpolator============动画开始与结束的地方速率改变比较慢,在中间的时候加速。
AccelerateInterpolator===================动画开始的地方速率改变比较慢,然后开始加速。
AnticipateInterpolator ==================开始的时候向后然后向前甩。
AnticipateOvershootInterpolator=============开始的时候向后然后向前甩一定值后返回最后的值。
BounceInterpolator=====================动画结束的时候弹起。
CycleInterpolator======================动画循环播放特定的次数,速率改变沿着正弦曲线。
DecelerateInterpolator===================在动画开始的地方快然后慢。
LinearInterpolator======================以常量速率改变。
OvershootInterpolator====================向前甩一定值后再回到原来位置。
PathInterpolator========================新增的,就是可以定义路径坐标,然后可以按照路径坐标来跑动;注意其坐标并不是 XY,
而是单方向,也就是我可以从0~1,然后弹回0.5 然后又弹到0.7 有到0.3,直到最后时间结束。