Android 动画: 补间动画、帧动画、属性动画

6 篇文章 1 订阅

概要:

3.0以前,android支持两种动画模式,

  • 补间动画(tween animation),透明、缩放、旋转、移动
  • 帧动画(frame animation),Frame Animation(AnimationDrawable对象):帧动画,就像GIF图片,
    通过一系列Drawable依次显示来模拟动画的效果。

在android3.0中又引入了一个新的动画系统:

  • 属性动画(property animation)。通过动画的方式改变对象的属性.属性动画更改的是对象的实际属性

(二)、动画资源分类:

  1. 属性动画:Property Animation
    放置在res/anim/目录下
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
  1. 帧动画:Frame Animation (Drawable Animation)
    放置在res/drawable/目录下
<!-- 注意:rocket.xml文件位于res/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>
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);

rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();

特别注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中调运,因为AnimationDrawable还未完全附着到window上,所以最好的调运时机是onWindowFocusChanged()方法中。

  1. 补间动画:Tween Animation (View Animation)

放置在res/animator/目录下

  • 透明度补间动画
  • 缩放补间动画
  • 旋转补间动画
  • 移动补间动画
    xml中设置动画
<set
  android:ordering=["together" | "sequentially"]>

    <objectAnimator
        android:propertyName="string"
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <animator
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <set>
        ...
    </set>
</set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.animtor.property_animator);
set.setTarget(myObject);
set.start();

java代码中使用动画:

ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();

同一个view同时多种动画

public void propertyValuesHolder(View view)  
    {  
        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,  
                0f, 1f);  
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,  
                0, 1f);  
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,  
                0, 1f);  
        ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();  
    }  

animatorset不仅可以同时执行动画,还可以排序执行动画

 public void playWithAfter(View view)  
    {  
        float cx = mBlueBall.getX();  
  
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",  
                1.0f, 2f);  
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",  
                1.0f, 2f);  
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,  
                "x",  cx ,  0f);  
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,  
                "x", cx);  
          
        /** 
         * anim1,anim2,anim3同时执行 
         * anim4接着执行 
         */  
        AnimatorSet animSet = new AnimatorSet();  
        animSet.play(anim1).with(anim2);  
        animSet.play(anim2).with(anim3);  
        animSet.play(anim4).after(anim3);  
        animSet.setDuration(1000);  
        animSet.start();  
    }  
1、playSequentially依次执行,playTogether同时执行。
2、animatorSet.play(anim1).before(anim2)与animatorSet.play(anim2).after(anim1)、                         
animatorSet.playTogether(anim1,anim2)是完全等价的

参考
Android应用开发之所有动画使用详解
Android应用坐标系统全面详解
Android应用开发之自定义View触摸相关工具类全解

狭义而言,动画一般就是指某个View组件的某个或者某些属性值在一段时间内不断变化的过程,这个变化过程往往有个起始值、结束值和一系列的中间值,ValueAnimator就是用来反映这个属性值变化过程的重要类。

如果将属性值的变化过程看做一个数学函数的话,从动画效果上来看它是连续的,但实际上它还是离散的,因为它实际上也就是通过插入中间值(简称插值)从而”一帧一帧”完成动画的,那每一帧在哪里取,取多少呢?这也就是ValueAnimator类主要完成的作用。

那到底ValueAnimator是怎么控制属性值的变化过程的呢?答案是借助TimeInterpolator和TypeEvaluator来帮忙!TimeInterpolator用来控制在哪里取,而TypeEvaluator用来控制取多少。</>(注:取多少个点进行插值是不确定的,例如动画持续时间1s,可能取60,也可能取54、57或者58个中间点进行插值)

每一个ValueAnimator其实就是一个的TimeInterpolator和一个TypeEvaluator的结合体。从数学的角度来看,ValueAnimator就是由TimeInterpolator和TypeEvaluator这两个简单函数组合而成的一个复合函数。用图来表述如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(0)ValueAnimator就是一个的TypeEvaluator和一个TimeInterpolator的结合体,所以该类有两个方法分别用来设置动画的TypeEvaluator和TimeInterpolator。 (1)setInterpolator方法可以不调用,默认是加速减速插值器AccelerateDecelerateInterpolator,但是如果调用且传入的参数为null的话,那么就会被设置成线性插值器LinearInterpolator (暂时不清楚为什么要这样做)。 (2)setEvaluator方法也可以不调用,默认会根据属性值的类型设置一个IntEvaluator或者FloatEvaluator。

参考
当数学遇上动画:讲述 ValueAnimator、TypeEvaluator 和 TimeInterpolator 之间的恩恩怨怨

一、补间动画:

View Animation就是一系列View形状的变换,如大小的缩放、透明度的改变、水平位置的改变、旋转位置改变,动画的定义既可以用java代码定义也可以用XML定义。

建议用XML定义。

用XML定义的动画放在/res/anim/文件夹内,XML文件的根元素为

<set> , 

二级节点可为

<alpha>,
<scale>,
<translate>,
<rotate>。

translate的几个重要的属性:

android:interpolator: 加速器,非常有用的属性,可以简单理解为动画的速度,可以是越来越快,也可以是越来越慢,
或者是先快后忙,或者是均匀的速度等等,对于值如下:
@android:anim/accelerate_interpolator: 越来越快::加速器
@android:anim/decelerate_interpolator:越来越慢::减速器
@android:anim/accelerate_decelerate_interpolator:先快后慢
@android:anim/anticipate_interpolator: 先后退一小步然后向前加速
@android:anim/overshoot_interpolator:快速到达终点超出一小步然后回到终点
@android:anim/anticipate_overshoot_interpolator:到达终点超出一小步然后回到终点
@android:anim/bounce_interpolator:到达终点产生弹球效果,弹几下回到终点
@android:anim/linear_interpolator:均匀速度。

在这里插入图片描述

android:duration: 动画运行时间,定义在多次时间(ms)内完成动画
android:startOffset: 延迟一定时间后运行动画
fromXDelta: X轴方向开始位置,可以是%,也可以是具体的像素 具体见图
toXDelta:   X轴方向结束位置,可以是%,也可以是具体的像素
fromYDelta: Y轴方向开始位置,可以是%,也可以是具体的像素
toYDelta:    Y轴方向结束位置,可以是%,也可以是具体的像素

动画的坐标:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

android动画坐标定义

补间动画例子:

public void alpha(View view) {
        // 设置开始和结束的透明度(0f-1f之间)
        AlphaAnimation aa = new AlphaAnimation(0.1f, 0.5f);

        // 设置动画的持续时间
        aa.setDuration(3000);
        // 设置重复播放次数
        aa.setRepeatCount(2);
        // 设置重复播放模式:reverse:折返,restart:重新开始
        aa.setRepeatMode(Animation.REVERSE);
        // 保持动画结束时的状态
        aa.setFillAfter(true);//动画结束后不动

        // 启动动画
        imgview.startAnimation(aa);

        // 动画监听事件
        aa.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

            }
        });
    }

    public void translate(View view) {

        // fromXDelta:x轴上的起始点,以像素为单位
        // toXDelta:x轴上的终点
        TranslateAnimation ta1 = new TranslateAnimation(0, 100f, 0, 100f);

        // fromXType:起点时,在X轴上变化时的参照类型,如:[Animation.RELATIVE_TO_SELF,0]:
        // 控件本身所在的坐标+0*控件本身的宽度
        // fromXValue: //左(x负数)右(x正数)上(y负数)下(y正数)
        TranslateAnimation ta = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
                2.0f, Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, -2.0f);

        // 设置动画的持续时间
        ta.setDuration(2000);
        // 设置重复播放次数
        ta.setRepeatCount(2);
        // 设置重复播放模式:reverse:折返,restart:重新开始
        ta.setRepeatMode(Animation.REVERSE);
        // 保持动画结束时的状态
        ta.setFillAfter(true);

        // 启动动画
        imgview.startAnimation(ta);
    }

    public void scale(View view) {
        // fromX:x轴的起点
        // pivotX:X轴上进行缩放的坐标值
        // pivotX:50-->:X轴上向右进行缩放的50个像素
        // pivotY:50-->:y轴上向下进行缩放的50个像素
        // from的x正数,y正数,则向第四象限移动
        ScaleAnimation sa = new ScaleAnimation(1, 2.0f, 1, 4.0f, 30, 0);

        // 设置动画的持续时间
        sa.setDuration(2000);
        // 设置重复播放次数
        sa.setRepeatCount(2);
        // 设置重复播放模式:reverse:折返,restart:重新开始
        sa.setRepeatMode(Animation.REVERSE);
        // 保持动画结束时的状态
        sa.setFillAfter(true);

        // 启动动画
        imgview.startAnimation(sa);
    }

    public void rotate(View view) {
        // fromDegrees:开始角度
        // toDegrees:结束角度//正数:顺时针,负数:逆时针
        RotateAnimation ra = new RotateAnimation(0, 180);

        // 设置动画的持续时间
        ra.setDuration(2000);
        // 设置重复播放次数
        ra.setRepeatCount(2);
        // 设置重复播放模式:reverse:折返,restart:重新开始
        ra.setRepeatMode(Animation.REVERSE);
        // 保持动画结束时的状态
        ra.setFillAfter(true);

        // 启动动画
        imgview.startAnimation(ra);
    }

    // 动画集合
    public void set(View view) {
        AnimationSet set = new AnimationSet(true);// 动画加速器

        // 设置开始和结束的透明度(0f-1f之间)
        AlphaAnimation aa = new AlphaAnimation(0.3f, 0.8f);//透明度
        // fromX:x轴的起点
        // pivotX:X轴上进行缩放的坐标值
        // pivotX:50-->:X轴上向右进行缩放的50个像素
        // pivotY:50-->:y轴上向下进行缩放的50个像素
        ScaleAnimation sa = new ScaleAnimation(1, 2.0f, 1, 4.0f, 30, 0);//缩放
        // fromXType:起点时,在X轴上变化时的参照类型,如:[Animation.RELATIVE_TO_SELF,0]:
        // 控件本身所在的坐标+0*控件本身的宽度
        TranslateAnimation ta = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
                2.0f, Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, -2.0f);//移动

        // 添加动画
        set.addAnimation(ta);
        set.addAnimation(aa);
        set.addAnimation(sa);

        set.setDuration(2000);
        set.setRepeatCount(2);

        // 启动动画
        imgview.startAnimation(set);
    }

二、帧动画:

Frame Animation(AnimationDrawable对象):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。
必须以

<animation-list>

为根元素,以

<item>

表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放
在/res/anim/或者/res/animator目录下。

【备注:】

SDK中提到,不要在onCreate()中调用start(),因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。

使用Animation-list实现等待旋转圆圈动画例子:

首先,建立anim文件夹,然后在里面建:imgloading.xml

<?xml version="1.0" encoding="utf-8"?>  
<!--  
    根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画  
    根标签下,通过item标签对动画中的每一个图片进行声明  
    android:duration 表示展示所用的该图片的时间长度  
 -->  
<animation-list  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false"  
    >  
    <item android:drawable="@drawable/black_01" android:duration="150"/>  
    <item android:drawable="@drawable/black_02" android:duration="150"/>  
    <item android:drawable="@drawable/black_03" android:duration="150"/>  
    <item android:drawable="@drawable/black_04" android:duration="150"/>  
    <item android:drawable="@drawable/black_05" android:duration="150"/>  
    <item android:drawable="@drawable/black_06" android:duration="150"/>  
    <item android:drawable="@drawable/black_07" android:duration="150"/>  
    <item android:drawable="@drawable/black_08" android:duration="150"/>  
    <item android:drawable="@drawable/black_09" android:duration="150"/>  
    <item android:drawable="@drawable/black_10" android:duration="150"/>  
    <item android:drawable="@drawable/black_11" android:duration="150"/>  
    <item android:drawable="@drawable/black_12" android:duration="150"/>  
</animation-list>  
img_loading = (ImageView)findViewById(R.id.img_loading);  
        img_loading.setBackgroundResource(R.anim.imgloading);  
        aniDraw = (AnimationDrawable)img_loading.getBackground();  
        aniDraw.start(); 

三、属性动画:

(一)、概念:

属性动画,这个是在Android 3.0中才引进的。

Property Animation属性动画故名思议就是通过动画的方式改变对象的属性.属性动画更改的是对象的实际属性, 在View
Animation(Tween Animation)补间动画中,其改变的是View的绘制效果,真正的View的属性保持不变。(原位置有效,换位置后无效)

可以将属性动画理解为增强版的补间动画。

比如无论如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。
而在PropertyAnimation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。

Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。

(二)、常用属性:

  1. Duration动画的持续时间,默认300ms。android:duration属性
  2. Time interpolation:时间插值。LinearInterpolator、AccelerateDecelerateInterpolator,定义动画的变化
    率。android:interpolator属性
  3. Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反
    向。android:repeatCount属性
  4. Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。,该元素的android:ordering属性指定该组动画是按次序播放还是同时播放。
  5. Frame refresh delay:帧刷新延迟(帧刷新频率,每个多久播放一帧);默认为10ms,但最终依赖系统的当前状态。

(三)、属性动画API:相关的类

  1. ObjectAnimator 动画的执行类(是ValueAnimator的子类,使用简单常用。少数场景下,由于其存在一些限制,再考虑使用ValueAnimator)
  2. ValueAnimator 动画的执行类
  3. AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
  4. AnimatorInflater 用户加载属性动画的xml文件
  5. TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
  6. TimeInterpolator 时间插值
    总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。

相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。

不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似

【备注:】
android:ordering说明一系列动画动作的执行顺序,有两个选择: sequentially 和together,顺序执行还是一起执行;
objectAnimator 是设定动画实施的对象;
duration是该动画动作执行从开始到结束所用的时间;
android:repeatCount=“infinite” 可以是整数或者infinite(无限大)
android:repeatMode=“restart” 可以是restart 或者 reverse
android:valueFrom=" " 整数|浮点数|颜色

属性动画例子:

   public void alpha(View view) {

        ObjectAnimator oa = ObjectAnimator.ofFloat(imgview, "alpha", 0, 0.1f,
                0.2f, 0.3f, 0.7f);

        oa.setDuration(2000);
        oa.setRepeatCount(2);
        oa.setRepeatMode(ObjectAnimator.RESTART);

        oa.start();

    }

    public void translate(View view) {

        ObjectAnimator oa = ObjectAnimator.ofFloat(imgview, "translationX", 0,
                100f, 50f, 100f, 50f);

        oa.setDuration(2000);
        oa.setRepeatCount(2);
        oa.setRepeatMode(ObjectAnimator.RESTART);

        oa.start();
    }

    public void scale(View view) {

        ObjectAnimator oax = ObjectAnimator.ofFloat(imgview, "scaleX", 1f, 2f,
                0.5f, 3f);
        ObjectAnimator oay = ObjectAnimator.ofFloat(imgview, "scaleY", 1f, 4f,
                1f, 2f);

        oax.setDuration(2000);
        oax.setRepeatCount(2);
        oay.setDuration(2000);
        oay.setRepeatCount(2);

        oax.start();
        oay.start();
    }

    public void rotate(View view) {

        ObjectAnimator oa = ObjectAnimator.ofFloat(imgview, "rotation", 0, 360);

        oa.setDuration(2000);
        oa.setRepeatCount(2);

        oa.start();
    }

    // 动画集合
    public void set(View view) {

        AnimatorSet set = new AnimatorSet();

        ObjectAnimator oa1 = ObjectAnimator.ofFloat(imgview, "alpha", 0, 0.1f,
                0.2f, 0.3f, 0.7f);
        ObjectAnimator oa2 = ObjectAnimator.ofFloat(imgview, "translationX", 0,
                100f, 50f, 100f, 50f);
        ObjectAnimator oa3 = ObjectAnimator.ofFloat(imgview, "rotation", 0, 360);

        set.setDuration(2000);

        List<Animator> list = new ArrayList<Animator>();
        list.add(oa1);
        list.add(oa2);
        list.add(oa3);

        // 顺序播放
        set.playSequentially(list);
        // set.playSequentially(oa1);

        set.start();
    }

参考:

使用Animation-list实现等待旋转圆圈动画

Android 用Animation-list实现逐帧动画

Android属性动画完全解析(上),初识属性动画的基本用法

Android开发(26)–补间动画(Tween)的实现

Android动画效果之Tween Animation(补间动画)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值