Android开发之Tween(补间动画)完全解析(上)——xml文件配置的实现

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dmk877/article/details/51912104

欢迎转载,转载请注明出处:http://blog.csdn.net/dmk877/article/details/51912104

 

相信不管做了多长时间开发的人都用过Tween动画,从刚开始工作到现在我也是用了N次Tween动画,但是每一次使用总感觉掌握的不够全面,所以花了点时间详细的总结了下Tween动画,其实在android中熟练掌握动画,能够帮助我们实现一些非常酷炫的效果从而使我们的app在交互或者用户体验上有一个更好的体验,鉴于此详细的学习动画还是很有必要的,相信通过本篇的学习大家会对Tween有个详细的了解,废话不多说进入正题。如有疑问请留言,如有谬误欢迎批评指正,谢谢。

在android中动画主要有三种,①帧动画(http://blog.csdn.net/dmk877/article/details/45893017)这篇文章已经详细的进行了讲解,②补间动画这也是这篇博客将要讨论的,③属性动画后续的文章中会和大家一起讨论。

Tween动画的分类

首先来了解下补间动画的分类,在android中补间动画可以分为四类:alpha(渐变)、scale(缩放)、translate(位移)、rotate(旋转)。在这四种动画里每种动画拥有它的独有的属性的同时又拥有相同的属性,其中

alpha:渐变透明度动画效果

scale:渐变缩放动画效果

translate:渐变位置移动动画效果

rotate:渐变旋转动画效果,这四种动画能够分别带来不同的效果体验,又能混合在一起完成酷炫的动画效果。
接下来我们就逐一详细的来学习这四种Tween动画

 

1、roate动画,旋转动画

 

在上面我们提到四种Tween动画都有其独有的属性又有其从Animation类继承的公共的属性,我们对这四种动画的讨论也将从两方面:一方面是独有的属性,另一方面是从Animation类继承的属性,从Animation这个类继承的属性用法都一样,这里以roate动画为例讨论一遍就行了。
 
1.1 独有属性
android:fromDegrees:动画开始时旋转的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
android:toDegrees: 动画结束时旋转到的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
android:pivotX:旋转点X轴坐标,float类型,可以是数值、百分数、百分数p三种样式,比如50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标,如果是50%;表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;如果是50%p,那么就是表示在当前控件的左上角加上父控件宽度的50%做为旋转点X坐标。
android:pivotY:旋转点Y轴坐标,取值及意义跟android:pivotX一样。
 
1.2 从Animation类继承的属性
android:duration:动画执行的时间,以毫秒为单位
android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态
android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍,这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹 起等等
 
1.3 roate动画的各属性讲解
 
1.3.1 fromDegress、toDegress属性
fromeDegress和toDegress这两个属性很好理解fromDegress表示从动画开始时旋转的角度,而toDegress当然就表示动画结束时旋转的角度了,如果你还不能理解透彻,相信下面的两个小例子可以帮助你,首先来看看运行效果。
它的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:duration= "1000">
</rotate>

最后XML文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?这是就要借助AnimationUtils这个类了,只需调用如下代码即可:

Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate);
ivGirl.startAnimation(animation);
从运行效果我们可以看到它从起始的0度旋转了360度。另外我们还能得出一个结论:默认的旋转的起始点是View的左上角顶点为起始点。需要注意的是这里开始旋转角度fromDegree与结束时的旋转角度toDegrees都是是相对于起始位置而言的什么意思呢?看下面这个例子你就会彻底理解。
我们修改下xml配置文件,修改如下:
<?xml version="1.0" encoding= "utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
         android:fromDegrees= "60"
         android:toDegrees= "90"
         android:fillAfter= "true"
         android:duration= "10000">
</rotate>
运行效果图:
在上述xml中我们设置的fromDegress是60度,toDegress是90度,从运行效果中可以看出点击运行按钮后,View首先立即旋转了60度作为旋转动画的起始位置,之后又旋转了30度到了90度,所以大家一定要理解清楚这里的toDegress是相对于起始位置而言的。
 
1.3.2 pivotX、pivotY
在上面我们也提到"pivotX"表示旋转点X轴坐标,也就是我们的View是以哪个点为基准而旋转的,它的值可以是数值、百分数、百分数p 三种样式,比如50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标;如果是50%表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为旋转点X坐标。
"pivotY"属性与"pivotX"属性一样。接下来就分别结合实例来详细理解下这三种取值吧。
  • 取值为数值
<?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= "75"
         android:pivotY= "125"
         android:duration= "10000">
</rotate>
从上面的解释可以知道,这里的旋转的X点的坐标是在原点的基础之上增加75px,而Y点的坐标是在原点的基础之上增加125px。由于图片的高度和宽度分别为150、250,运行在这是480*320的模拟器此时1dp=1px)所以我们设置的pivotX=75,pivotY=125也就刚好在图片的正中间,运行效果如下
                
注意在这张美女图片的下巴上有个小白点,这个小白点是图片的中心位置。我们发现它的旋转点就是这个View的中心点。
  • 取值为百分数
<?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%"
         android:duration= "10000">
</rotate>

pivotX的值当取百分数时表示在原点坐标(View的左上角的那个点)的基础之上加上自己的宽度,那么当取50%时,表示在原点坐标的基础上加上的自己宽度的50%也就是图片的正中心,为了防止大家审美疲劳我换了张美女图片,中间的小白点不是特别明显,运行效果如下:

我们发现它的旋转的中心就是View的中心。
  • 取值为百分数后面加p
取值为百分数后加p表示旋转点在原点的基础之上加上父控件的百分值。如pivotX取值为50%p就表示旋转点的x坐标在原点基础之上父控件宽度的50%。经计android:pivotX="23%p",android:pivotY="26%p"时旋转的点处于View的中间,480*26/100约等于125,即旋转点的Y坐标在坐标原点的基础之上加上125与(1)类似
<?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= "23%p"
         android:pivotY= "26%p"
         android:duration= "10000">
</rotate>
运行效果与上面一样,就不再上图了。
 
1.3.3 android:fillAfter
这个属性设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,true表示停留在最后一帧,false表示不停留在最后一帧
<?xml version="1.0" encoding= "utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
         android:fromDegrees= "0"
         android:toDegrees= "300"
         android:pivotX= "50%"
         android:pivotY= "50%"
         android:fillAfter= "true"
         android:duration= "1000">
</rotate>
运行效果:
上面的xml属性动画的配置中,我们将fillAfter的值设置为true,可以看到它停留在了最后一帧。

1.3.4 android:fillBefore
它表示View动画结束时是否会停留在动画开始的状态
<?xml version="1.0" encoding= "utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
         android:fromDegrees= "0"
         android:toDegrees= "300"
         android:pivotX= "50%"
         android:pivotY= "50%"
         android:fillEnabled= "true"
         android:fillBefore= "true"
         android:duration= "1000">
</rotate>
运行效果:
可以看到图片旋转300度后又回到了最开始的状态。
 
1.3.5 android:repeatMode
重复类型,取值为reverse|restart,reverse:表示倒序回放,restart:表示重新放一遍,这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
<?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%"
         android:repeatMode= "restart"
         android:repeatCount= "2"
         android:fillEnabled= "true"
         android:fillBefore= "true"
         android:duration= "1000">
</rotate>
reverse:表示倒序回放,restart:表示重新放一遍
android:repeatMode="restart"                   android:repeatMode="reverse"
                             
在上述xml文件配置中我们将repeatCount设置为2,从运行效果可以看出两者的区别restart是连续播放,而reverse播放一遍后倒序播放了一遍。
 
1.3.6 android:repeatCount
动画重复的次数(注意是重复的次数),可以是你想循环播放的次数数值,也是可以取值infinite:表示无限循环,这个属性在上面也介绍用到了,就不再上图片了。
 
2 、Alpha动画(渐变透明度动画)
 
2.1 Alpha的特有属性
android:fromAlpha:动画开始时的透明度,变化范围为0.0-1.0,0.0表示完全透明,1.0表示完全不透明
android:toAlpha:动画结束是的透明度,变化范围和意义同上。
其实它的意义很好理解,一个View透明度变化,肯定是从一个透明度变为另一个透明度。这样就需要两个属性fromAlpha和toAlpha,这个变化的过程是android自动帮我们实现的,也就是说假如从完全透明,到完全不透明这中间的过程是谷歌工程师为我们提供好的,当然我们也可以改变。
<?xml version="1.0" encoding= "utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromAlpha= "0.0"
        android:toAlpha= "1.0"
        android:repeatCount= "2"
        android:duration= "3000"
        android:fillAfter= "true" >
</alpha>
在上面的xml配置中我们设置了图片的透明度从0逐渐变化到1,可以看到运行效果从完全不透明变化到完全透明。
 
2.2 从Animaton类继承的属性
android:duration:动画执行的时间,以毫秒为单位
android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,false?
android:fillBefore:与fillEnabled相同
android:fillAfter:true|false,true:动画结束时,将保持动画最后时的状态
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍
这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
android:repeatCount:动画重复的次数,可以是你想循环播放的次数,也是可以是infinite:表示无限循环
android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
这些公共的属性我们在roate动画中已经通过效果一一解释过了,就不再重复演示了。
   
3、translate(位移动画)

3.1 位移动画独有的属性
android:fromXDelta:起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,具体意义在roate已经演示过。
android:fromYDelta:起始点Y坐标,可以是数值、百分数、百分数p三种样式。
android:toXDelta:结束点X坐标
android:toYDelta:结束点Y坐标
<?xml version="1.0" encoding= "utf-8"?>
<translate
    xmlns:android ="http://schemas.android.com/apk/res/android" 
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="200"
    android:toYDelta="300"
    android:duration="5000">
</translate>
运行效果:
 
可以看到美女逐渐的离开了我们的视线。
 
3.2 从Animation类继承的属性
android:duration:动画执行的时间,以毫秒为单位
android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,
android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义
默认值是true,视图会停留在动画开始的状态
android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等
 
4、scale缩放动画
 
4.1 独有属性
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一样
<?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%"
       android:duration= "5000">
  
</scale>
运行效果:
可以清楚的看到这张图片先是放大了两倍然后逐渐恢复原状。
 
4.2 从Animation类继承的属性
android:duration:动画执行的时间,以毫秒为单位
android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态
android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
 
5、set标签的使用
 
到这里可能有的同学会说动画太单调,其实学好Tween动画你能做出好多比较酷炫的动画,这就要用到set标签了从它的名字我们也能够猜出来它是干什么用的,它就是一组动画的集合,也就是说我们可以让一个View同时执行多个动画,set标签自已是没有属性的,他的属性都是从Animation继承而来,但当它们用于Set标签时,就会对Set标签下的所有子控件都产生作用。
它所拥有的属性我们上面也介绍到了
android:duration:动画执行的时间,以毫秒为单位
android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,false?
android:fillBefore:与fillEnabled相同
android:fillAfter:true|false,true:动画结束时,将保持动画最后时的状态
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
android:repeatCount:动画重复的次数,可以是你想循环播放的次数,也是可以是infinite:表示无限循环
android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
接着们就来看一个组合动画吧
xml文件
<?xml version="1.0" encoding= "utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
   
    <alpha
        android:fromAlpha= "0.0"
        android:toAlpha= "1.0"
        android:duration= "3000" />
   
    <scale
        android:fromXScale= "0.0"
        android:toXScale= "1.0"
        android:fromYScale= "0.0"
        android:toYScale= "1.0"
        android:pivotX= "50%"
        android:pivotY= "50%"
        android:duration= "3000" />
   
    <rotate
        android:fromDegrees= "0"
        android:toDegrees= "720"
        android:pivotX= "50%"
        android:pivotY= "50%"
        android:duration= "3000"/>
   
     <translate
        android:startOffset= "3000"
        android:fromXDelta= "0"
        android:fromYDelta= "0"
        android:toXDelta= "85"
        android:toYDelta= "0"
        android:duration= "1000" />
    
    <alpha
        android:startOffset= "4000"
        android:fromAlpha= "1.0"
        android:toAlpha= "0.0"
        android:duration= "1000" />

</set>
我们用它来实现一个稍微酷炫点的动画
可以看到这个组合动画展示了美女从出厂到离开的整个过程。
接着来看下从Animation继承的几个属性的讲解
android:duration:这个我相信不用多说了,就是整个动画执行的时间
android:fillEnabled:默认值是false。如果是true,动画将会应用fillBefore值;否则,fillBefore的值会被忽略,transformation会在动画结束的时候被应用。(这个属性的出现是谷歌为了兼容之前的版本)
android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
 
6、interpolator插值器
 
首先来看下官网给出的interpolator的定义:interpolaotor定义了动画变化的速率,它允许基础动画(alpha, scale, translate, rotate)加速,减速,重复变化等等。在补间动画中,我们一般只定义关键帧(首帧和尾帧),然后由系统自动生成中间帧,生成中间帧的这个过程可以成为“插值”。插值器定义了动画变化的速率,提供不同的函数定义变化值相对于时间的变化规则,可以定义各种各样的非线性变化函数,比如加速、减速等。下面是几种常见的插值器:
Interpolator对象 资源ID 功能作用
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速再减速
AccelerateInterpolator @android:anim/accelerate_interpolator 加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先回退一小步然后加速前进
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 先回退一小步然后加速前进,超出终点一小步后再回到终点
BounceInterpolator @android:anim/bounce_interpolator 最后阶段弹球效果
CycleInterpolator @android:anim/cycle_interpolator 周期运动
DecelerateInterpolator @android:anim/decelerate_interpolator 减速
LinearInterpolator @android:anim/linear_interpolator 匀速
OvershootInterpolator @android:anim/overshoot_interpolator 快速到达终点并超出一小步最后回到终点
怎么用它呢?它的用法也非常简单只需要在xml文件中加一句话就行了
<?xml version="1.0" encoding="utf-8"?>
<translate 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/bounce_interpolator" 
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="200"
    android:toYDelta="300"
    android:duration="5000">
</translate>

如果只简单地引用这些插值器还不能满足需要的话,我们要考虑一下个性化插值器。我们可以创建一个插值器资源修改插值器的属性,比如修改AnticipateInterpolator的加速速率,调整

CycleInterpolator的循环次数等。为了完成这种需求,我们需要创建XML资源文件,然后将其放于/res/anim下,然后再动画元素中引用即可。我们先来看一下几种常见的插值器可调整的属性:

<accelerateDecelerateInterpolator> 无
<accelerateInterpolator> android:factor 浮点值,加速速率,默认为1
<anticipateInterploator> android:tension 浮点值,起始点后退的张力、拉力数,默认为2
<anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮点值,拉力的倍数,默认为1.5(2  * 1.5)
<bounceInterpolator> 无
<cycleInterplolator> android:cycles 整数值,循环的个数,默认为1
<decelerateInterpolator> android:factor 浮点值,减速的速率,默认为1
<linearInterpolator> 无
<overshootInterpolator> 浮点值,超出终点后的张力、拉力,默认为2
接下来就来看几个不是特别好理解的插值器的运行效果,没有演示到的,大家可以自己动手运行看看效果

  • anticipateInterploator

先回退一小步然后加速前进

<?xml version="1.0" encoding="utf-8"?>
<translate 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/anticipate_interpolator"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="0"
    android:fillAfter="true"
    android:toYDelta="480"
    android:duration="3000">
</translate>
运行效果:
可以看到它先回退一段距离然后再加速前进。
在上面我们也提到有几种插值器是支持对属性的调整的,我们就以anticipateInterploator为例,这时我们需要新建一个xml文件放置于/res/anim文件夹下,比如我们新建一个my_anticipate_interpolator.xml文件,它的内容如下:
<?xml version="1.0" encoding="utf-8"?>  
<anticipateInterpolator  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:tension="4.0"/> 
可以看到这里将tension的值改为了4,引用它的方法也非常简单如下:
<?xml version="1.0" encoding="utf-8"?>
<translate 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@anim/my_anticipate_interpolator"
    。。。。。。>
</translate>
运行效果:
可以明显的看出小球回退的距离要远一点。当然你也可以更改其他插值器的其它属性,从而符合自己的要求。
  • AnticipateOvershootInterpolator

可以看到AnticipateOvershootInterpolator的运行效果先回退一小步然后加速前进,超出终点一小步后再回到终点。

  • BounceInterpolator

可以看到在小球在最后阶段的效果是弹球效果。

  • OvershootInterpolator



好了到这里关于四种Tween动画的讨论就结束了,相信到这里大家对Tween动画的xml文件配置应该有一个比较详细的理解了,那么下一篇将和大家一起来探讨用代码来完成Tween动画,敬请期待。

如果这篇文章对你有帮助,就顶一下呗。

源码猛戳这里

如有疑问请留言,如有谬误欢迎批评指正,谢谢。

 
 
 




展开阅读全文

没有更多推荐了,返回首页