android中的动画全解析

Android为我们提供了2中动画

一: Tween Animation 渐变动画 通过对特定对象做图像的变换,例如: 平移, 缩放,旋转, 淡入淡出 等。

二: Frame Animation 帧动画 创建一个淡入阿瓦不了可以按照指定的时间间隔一个一个显示。顺序播放

下面我们就详细介绍一下这两中动画:

首先我们介绍 渐变动画:

1. Tween Animation

1. 渐变动画有四种样式:

alpha: 渐变透明度

scale: 缩放尺寸伸缩动画

translate: 移动动画效果

rotate : 旋转动画

2.使用方式:

2.1 可以通过xml资源文件设置, 然后通过AnimationUtils的LoadAnimation方法加载

举例:

alpha: 渐变透明度

<alpha android:interpolator= “@android:anim/accelerate_decelerate_interpolator”  
            android:fromAlpha="1.0"  
            android:toAlpha="0.0"  
            android:duration="3000"  
        ></alpha>   
        <!--   
    interpolator:指定一个动画的插入器,用来控制动画的速度变化    
        fromAlpha:动画起始时透明度  
                      0.0表示完全透明  
                      1.0表示完全不透明  
                      以上值取0.0-1.0之间的float数据类型的数字  
        toAlpha:动画结束时透明度  
        duration:持续时间 -->  

scale: 缩放尺寸伸缩动画

<scale  
            android:interpolator= “@android:anim/accelerate_decelerate_interpolator”  
            android:fromXScale=”0.0″  
            android:toXScale=”1.4″  
            android:fromYScale=”0.0″  
            android:toYScale=”1.4″  
            android:pivotX=”50%”  
            android:pivotY=”50%”  
            android:fillAfter=”false”  
            android:startOffset=“700”  
            android:duration=”700″  
            android:repeatCount=”10″ />  
       <!--    
        fromXScale[float]:为动画起始时,X坐标上的伸缩尺寸,0.0表示收缩到没有  
        fromYScale[float]:为动画起始时,Y坐标上的伸缩尺寸,0.0表示收缩到没有  
                1.0表示正常无伸缩  
                值小于1.0表示收缩  
                值大于1.0表示放大  
    toXScale[float]:为动画结束时,X坐标上的伸缩尺寸  
    toYScale[float]:为动画结束时,X坐标上的伸缩尺寸  
    pivotX[float]:为动画相对于物件的X坐标的开始位置  
    pivotY[float]:为动画相对于物件的X、Y坐标的开始位置     
            50,50%,50%p。这三种写法就分别代表了ABSOLUTE,RELATIVE_TO_SELF和RELATIVE_TO_PARENT。   
            属性值说明:从0%-100%中取值,50%为物件的X或Y方向坐标上的中点位置  
    fillAfter[boolean]:当设置为true ,该动画转化在动画结束后被应用  
    startOffset[long]:动画之间的时间间隔,从上次动画停多少时间开始执行下个动画  
    repeatCount[int]:动画的重复次数 -->  


translate: 移动动画效果

<translate  
    android:interpolator=”@android:anim/accelerate_decelerate_interpolator”  
    android:fromXDelta=”30″  
    android:toXDelta=”-80″  
    android:fromYDelta=”30″  
    android:toYDelta=”300″  
    android:duration=”2000″ />  
t;!--         
fromXDelta:为动画起始时 X坐标上的位置     
toXDelta: 为动画结束时 X坐标上的位置        
fromYDelta: 为动画起始时 Y坐标上的位置  
toYDelta:为动画结束时 Y坐标上的位置 -->  

rotate : 旋转动画

<rotate  
    android:interpolator=”@android:anim/accelerate_decelerate_interpolator”  
    android:fromDegrees=”0″  
    android:toDegrees=”+350″  
    android:pivotX=”50%”  
    android:pivotY=”50%”  
    android:duration=”3000″ />  
t;!--         
fromDegrees:动画起始时物件的角度  
toDegrees:动画结束时物件旋转的角度 可以大于360度  
            当角度为负数——表示逆时针旋转  
            当角度为正数——表示顺时针旋转  
            (负数from——to正数:顺时针旋转)  
            (负数from——to负数:逆时针旋转)  
            (正数from——to正数:顺时针旋转)  
            (正数from——to负数:逆时针旋转)  
  
pivotX;:为动画相对于物件的X、Y坐标的开始位置  
pivotY: 为动画相对于物件的X、Y坐标的开始位置  
            50%为物件的X或Y方向坐标上的中点位置 -->  


2.2 使用 Anmation的相关子类构造函数来初始化animation对象。

 在android的sdk中提供了想要的类,animation类派生出了    aplhaAnimation   ScaleAnimation   TranslateAnimation  RotateAnimation 分别实现了平移,旋转,渐变,尺寸,和透明度等动画

举例:

//在代码中定义 动画实例对象
private Animation myAnimation_Alpha;
private Animation myAnimation_Scale;
private Animation myAnimation_Translate;
private Animation myAnimation_Rotate;

    //根据各自的构造方法来初始化一个实例对象
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);

myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
             Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

myAnimation_Translate = new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f);

myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
               Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
1. AlphaAnimation
AlphaAnimation类对象定义
   1. private AlphaAnimation myAnimation_Alpha;
AlphaAnimation类对象构造
AlphaAnimation(float fromAlpha, float toAlpha) 
//第一个参数fromAlpha为 动画开始时候透明度
//第二个参数toAlpha为 动画结束时候透明度
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);
//说明: 
//                0.0表示完全透明
//                1.0表示完全不透明
设置动画持续时间
myAnimation_Alpha.setDuration(5000);
//设置时间持续时间为 5000毫秒

2. ScaleAnimation
ScaleAnimation类对象定义

private ScaleAnimation myAnimation_Scale;
ScaleAnimation类对象构造
ScaleAnimation(float fromX, float toX, float fromY, float toY,
           int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) 
//第一个参数fromX为动画起始时 X坐标上的伸缩尺寸    
//第二个参数toX为动画结束时 X坐标上的伸缩尺寸     
//第三个参数fromY为动画起始时Y坐标上的伸缩尺寸    
//第四个参数toY为动画结束时Y坐标上的伸缩尺寸  
/*说明:
                    以上四种属性值    
                    0.0表示收缩到没有 
                    1.0表示正常无伸缩     
                    值小于1.0表示收缩  
                    值大于1.0表示放大
*/
//第五个参数pivotXType为动画在X轴相对于物件位置类型  
//第六个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第七个参数pivotXType为动画在Y轴相对于物件位置类型   
//第八个参数pivotYValue为动画相对于物件的Y坐标的开始位置
myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
             Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
设置动画持续时间
myAnimation_Scale.setDuration(700);
//设置时间持续时间为 700毫秒
3. TranslateAnimation
ranslateAnimation类对象定义
private TranslateAnimation myAnimation_Translate;
TranslateAnimation类对象构造
TranslateAnimation(float fromXDelta, float toXDelta,
                       float fromYDelta, float toYDelta) 
//第一个参数fromXDelta为动画起始时 X坐标上的移动位置    
//第二个参数toXDelta为动画结束时 X坐标上的移动位置      
//第三个参数fromYDelta为动画起始时Y坐标上的移动位置     
//第四个参数toYDelta为动画结束时Y坐标上的移动位置
设置动画持续时间
myAnimation_Translate = new TranslateAnimation(10f, 100f, 10f, 100f);
myAnimation_Translate.setDuration(2000);
//设置时间持续时间为 2000毫秒

4. RotateAnimation
RotateAnimation类对象定义

private RotateAnimation myAnimation_Rotate;
RotateAnimation类对象构造
RotateAnimation(float fromDegrees, float toDegrees, 
            int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
//第一个参数fromDegrees为动画起始时的旋转角度    
//第二个参数toDegrees为动画旋转到的角度   
//第三个参数pivotXType为动画在X轴相对于物件位置类型  
//第四个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第五个参数pivotXType为动画在Y轴相对于物件位置类型   
//第六个参数pivotYValue为动画相对于物件的Y坐标的开始位置
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
               Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
设置动画持续时间
myAnimation_Rotate.setDuration(3000);
//设置时间持续时间为 3000毫秒

如何Java代码中使用动画效果
使用从View父类继承过来的方法startAnimation()来为View或是子类View等等添加一个动画效果
public void startAnimation (Animation animation)
view.startAnimation(myAnimation_Alpha);
view.startAnimation(myAnimation_Scale);
view.startAnimation(myAnimation_Translate);
view.startAnimation(myAnimation_Rotate);

 3: android sdk通过Interpolator 控制动画的运行

首先要了解为什么需要插值器,因为在补间动画中,我们一般只定义关键帧(首帧或尾帧),然后由系统自动生成中间帧,生成中间帧的这个过程可以成为“插值”。插值器定义了动画变化的速率,提供不同的函数定义变化值相对于时间的变化规则,可以定义各种各样的非线性变化函数,比如加速、减速等。下面是几种常见的插值器:

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 快速到达终点并超出一小步最后回到终点


然后我们可以这样使用一个插值器:

<set android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
<alpha android:interpolator="@android:anim/accelerate_interpolator"
 .../>


如果只简单地引用这些插值器还不能满足需要的话,我们要考虑一下个性化插值器。我们可以创建一个插值器资源修改插值器的属性,比如修改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
下面我们就拿最后一个插值器来举例:

<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:tension="7.0"/>

上面的代码中,我们把张力改为7.0,然后将此文件命名为my_overshoot_interpolator.xml,放置于/res/anim下,我们就可以引用到自定义的插值器了:

<scale xmlns:android="http://schemas.android.com/apk/res/android"  
    android:interpolator="@anim/my_overshoot_interpolator"  
    .../>  


如果以上这些简单的定义还不能满足我们的需求,那么我们就需要考虑一下自己定义插值器类了。
我们可以实现Interpolator接口,因为上面所有的Interpolator都实现了Interpolator接口,这个接口定义了一个方法:float getInterpolation(float input);
此方法由系统调用,input代表动画的时间,在0和1之间,也就是开始和结束之间。
线性(匀速)插值器定义如下:

public float getInterpolation(float input) {  
    return input;  
}  
加速减速插值器定义如下:
public float getInterpolation(float input) {  
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;  
}  
有兴趣的话,大家可以尝试一下自定义一个插值器。


下面我从网上找了个相对形象的例子来介绍系统自带的加速器,想看的就看看,不想看的完全可以跳过。


http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0110/2292.html


应用:
先来介绍一下旋转动画的使用,布局文件/res/layout/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:orientation="vertical"  
  android:layout_width="fill_parent"  
  android:layout_height="fill_parent"  
  android:background="#FFFFFF">  
  <ImageView  
        android:id="@+id/piechart"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_gravity="center_horizontal"  
        android:src="@drawable/piechart"/>  
  <Button  
        android:id="@+id/positive"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="顺时针"  
        android:onClick="positive"/>  
  <Button  
        android:id="@+id/negative"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="逆时针"  
        android:onClick="negative"/>       
</LinearLayout>  


我们定义了一个ImageView,用于显示一个饼状图,演示旋转动画,然后定义了两个按钮,用以运行编码实现的动画。动画定义文件/res/anim/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">  
    <rotate  
        android:fromDegrees="0"  
        android:toDegrees="+360"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:duration="5000"/>  
</set>  


最后再来看一下RotateActivity.java代码:
public class RotateActivity extends Activity {  
  
    private int currAngle;  
    private View piechart;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.rotate);  
  
        piechart = findViewById(R.id.piechart);  
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);  
        piechart.startAnimation(animation);  
    }  
      
    public void positive(View v) {  
        Animation anim = new RotateAnimation(currAngle, currAngle + 180, Animation.RELATIVE_TO_SELF, 0.5f,  
                Animation.RELATIVE_TO_SELF, 0.5f);  
        /** 匀速插值器 */  
        LinearInterpolator lir = new LinearInterpolator();  
        anim.setInterpolator(lir);  
        anim.setDuration(1000);  
        /** 动画完成后不恢复原状 */  
        anim.setFillAfter(true);  
        currAngle += 180;  
        if (currAngle > 360) {  
            currAngle = currAngle - 360;  
        }  
        piechart.startAnimation(anim);  
    }  
      
    public void negative(View v) {  
        Animation anim = new RotateAnimation(currAngle, currAngle - 180, Animation.RELATIVE_TO_SELF, 0.5f,  
                Animation.RELATIVE_TO_SELF, 0.5f);  
        /** 匀速插值器 */  
        LinearInterpolator lir = new LinearInterpolator();  
        anim.setInterpolator(lir);  
        anim.setDuration(1000);  
        /** 动画完成后不恢复原状 */  
        anim.setFillAfter(true);  
        currAngle -= 180;  
        if (currAngle < -360) {  
            currAngle = currAngle + 360;  
        }  
        piechart.startAnimation(anim);  
    }  
}  



    4.动画的运行
模式
        独占模式; 即程序主线程进入循环,根据动画指令不断刷新屏幕,直至动画结束
        终端模式: 即有单独一个线程时间计数,每隔一定的时间向主线程发送通知,主线程接到通知后更新屏幕。




二:Frame Animation 动画:
    android通过AnimationDrawable来定义
    可以在xml定义,也可以使用AnimationDrawable中的API定义,由于Tween Animation与Frame Aniamtion
    有着很大的不同,因此xml定义的格式也不一样,首先是 animation-list根节点,animation-list根节点中包含多个item子节点,每个item节点定义一帧动画,当前帧的drawable资源和当前帧持续的时间

<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot=["true" | "false"] >  
    <item  
        android:drawable="@[package:]drawable/drawable_resource_name"  
        android:duration="integer" />  
</animation-list> 


需要注意的是:
<animation-list>元素是必须的,并且必须要作为根元素,可以包含一或多个<item>元素;android:onshot如果定义为true的话,此动画只会执行一次,如果为false则一直循环。
<item>元素代表一帧动画,android:drawable指定此帧动画所对应的图片资源,android:druation代表此帧持续的时间,整数,单位为毫秒。


我们新建一个名为anim的工程,将四张连续的图片分别命名为f1.png,f2.png,f3.png,f4.png,放于drawable目录,然后新建一个frame.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/f1" android:duration="300" />  
    <item android:drawable="@drawable/f2" android:duration="300" />  
    <item android:drawable="@drawable/f3" android:duration="300" />  
    <item android:drawable="@drawable/f4" android:duration="300" />  
</animation-list>  


我们可以将frame.xml文件放置于drawable或anim目录,官方文档上是放到了drawable中了,大家可以根据喜好来放置,放在这两个目录都是可以运行的。


我们定义了一个ImageView作为动画的载体,然后定义了两个按钮,分别是停止和启动动画。
接下来介绍一下如何通过加载动画定义文件来实现动画的效果。我们首先会这样写:
 image = (ImageView) findViewById(R.id.frame_image);  
          
        image.setBackgroundResource(R.anim.frame);  
        AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
        anim.start();  


看似十分完美,跟官方文档上写的一样,然而当我们运行这个程序时会发现,它只停留在第一帧,并没有出现我们期望的动画,也许你会失望的说一句:“Why?”,然后你把相应的代码放在一个按钮的点击事件中,动画就顺利执行了,再移回到onCreate中,还是没效果,这个时候估计你会气急败坏的吼一句:“What the fuck!”。但是,什么原因呢?如何解决呢?
出现这种现象是因为当我们在onCreate中调用AnimationDrawable的start方法时,窗口Window对象还没有完全初始化,AnimationDrawable不能完全追加到窗口Window对象中,那么该怎么办呢?我们需要把这段代码放在onWindowFocusChanged方法中,当Activity展示给用户时,onWindowFocusChanged方法就会被调用,我们正是在这个时候实现我们的动画效果。当然,onWindowFocusChanged是在onCreate之后被调用的,如图:
 @Override  
    public void onWindowFocusChanged(boolean hasFocus) {  
        super.onWindowFocusChanged(hasFocus);  
        image.setBackgroundResource(R.anim.frame);  
        AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
        anim.start();  
    }  


如果在有些场合,我们需要用纯代码方式实现一个动画,我们可以这样写:
AnimationDrawable anim = new AnimationDrawable();  
for (int i = 1; i <= 4; i++) {  
    int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());  
    Drawable drawable = getResources().getDrawable(id);  
    anim.addFrame(drawable, 300);  
}  
anim.setOneShot(false);  
image.setBackgroundDrawable(anim);  
anim.start();  

学习不易,且学且珍惜。。。。。。。。


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 快速到达终点并超出一小步最后回到终点

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。