文章主要内容来源《Android开发艺术探索》,部分内容来源网上的文章,文中会有链接。

Android系统提供了两个动画框架:属性动画框架和View动画框架。 两个动画框架都是可行的选项,但是属性动画框架通常是首选的使用方法,因为它更灵活,并提供更多的功能。 除了这两个框架,还可以使用Drawable动画(即逐帧动画,AnimationDrawable),它允许你加载Drawable资源并逐帧地显示它们。

  1. View动画框架(补间动画)
    View动画框架中一共提供了AlphaAnimation(透明度动画)、RotateAnimation(旋转动画)、ScaleAnimation(缩放动画)、TranslateAnimation(平移动画)四种类型的补间动画;并且View动画框架还提供了动画集合类(AnimationSet),通过动画集合类(AnimationSet)可以将多个补间动画以组合的形式显示出来。补间动画的实现,一般会采用xml文件的形式,那样代码会更容易书写和阅读,同时也更容易复用。

  2. 属性动画框架
    与属性动画相比View动画存在一个缺陷,View动画改变的只是View的显示,而没有改变View的响应区域,并且View动画只能对View做四种类型的补间动画。因此Google在Android3.0(API级别11)及其后续版本中添加了属性动画框架,从名称中就可以知道只要某个类具有属性(即该类含有某个字段的set和get方法),那么属性动画框架就可以对该类的对象进行动画操作(其实就是通过反射技术来获取和执行属性的get,set方法),同样属性动画框架还提供了动画集合类(AnimatorSet),通过动画集合类(AnimatorSet)可以将多个属性动画以组合的形式显示出来。

作者:ForeverCy
链接:http://www.jianshu.com/p/b117c974deaf
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一、View动画

View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation。四种动画可以用这四个类通过代码实现,也可以使用XML文件来定义。建议使用XML来定义动画,因为XML格式可读性好而且方便复用。

名称 标签 子类
平移动画 TranslateAnimation
缩放动画 ScaleAnimation
选中动画 RotateAnimation
透明度动画 AlphaAnimation
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator=""
    android:shareInterpolator="true|false">
    <translate
        android:fromXDelta=""
        android:toXDelta=""
        android:fromYDelta=""
        android:toYDelta="" />
    <scale
        android:fromXScale=""
        android:toXScale=""
        android:fromYScale=""
        android:toYScale=""
        android:pivotX=""
        android:pivotY="" />
    <rotate
        android:fromDegrees=""
        android:toDegrees=""
        android:pivotX=""
        android:pivotY="" />
    <alpha
        android:fromAlpha=""
        android:toAlpha="" />

    <set>
        <!--set嵌套set-->
    </set>
</set>

View动画可以是单个动画,也可以由一系列动画组成,使用标签实现组合。标签对应AnimationSet类,内部也可以嵌套其他动画集合。

android:interpolator表示动画集合所使用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。这个属性可以不指定,默认是@android:anim/accelerate_decelerate_interpolator,即加速减速插值器。
android:shareInterpolator表示集合中的动画是否和集合共享同一个插值器。如果集合不指定插值器,那么子动画就需要单独指定所需要的插值器或者使用默认值。

android:fromXDelta x的起始值
android:toXDelta x的结束值
android:fromYDelta y的起始值
android:toYDelta y的结束值

android:fromXScale 水平方向缩放的起始值
android:toXScale 水平方向缩放的结束值
android:fromYScale 竖直方向缩放的起始值
android:toYScale 竖直方向缩放的结束值
android:pivotX 缩放的轴点的x坐标
android:pivotY 缩放的轴点的y坐标

android:fromDegrees 旋转开始的角度
android:toDegrees 旋转结束的角度
android:pivotX 旋转的轴点的x坐标
android:pivotY 选中的轴点的y坐标

android:fromAlpha 透明度的起始值
android:toAlpha 透明度的结束值

一些其他常用属性

android:duration 动画的持续时间
android:fillBefore 动画结束后是否回到执行前的位置
android:fillAfter 动画结束后是否停留在结束位置
android:interpolator 动画使用的插值器
android:startOffset 动画执行之前的等待时间
android:repeatCount 动画重复执行的次数
xml属性都有对应的set方法

使用示例

首先编写动画xml文件test_anim.xml

Button mButton = (Button)findViewById(R.id.button);
Animation animation = AnimationUtils.loadAnimation(context, R.anim.test_anim);
mButton.startAnimation(animation);

也可以通过代码实现

AlphaAnimation animation = new AlphaAnimation(0, 1);
animation.setDuration(300);
mButton.startAnimation(animation);

使用setAnimationListener方法可以给动画添加过程监听。

View动画的特殊使用场景

LayoutAnimation控制ViewGroup的子View的出场效果,使用步骤如下:
  1. 定义LayoutAnimation,文件名res/anim/anim_layout.xml
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="150"
    android:animationOrder="normal"
    android:animation="@anim/anim_item"/>

android:delay 子元素开始动画的时间延迟
android:animationOrder 子元素动画的顺序。有normal(顺序)、reverse(逆向)、random(随机)三种顺序。
android:animation 子元素入场的具体动画

  1. 定义子元素具体的入场动画,文件名res/anim/anim_item.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="500"
    android:toXDelta="0"/>
  1. 为Viewgroup指定 android:layoutAnimation属性,比如ListView:
<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutAnimation="@anim/anim_layout" />

除了通过xml中指定layoutAnimation属性,也可以通过LayoutAnimationController来实现:

Animation animation = AnimationUtils.loadAnimation(context, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);
Activity的切换效果

使用overridePendingTransition(int enterAnim, int exitAnim)方法实现Activity的切换动画,这个方法必须在startActivity()或者finish()之后调用才能生效。
Fragment也可以添加切换动画,通过FragmentTransaction中的setCustomAnimations()方法实现。

二、帧动画

帧动画的标签是,对应AnimationDrawable类。
示例代码

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/img1" android:duration="500"/>
    <item android:drawable="@drawable/img2" android:duration="500"/>
    <item android:drawable="@drawable/img3" android:duration="500"/>
</animation-list>
Button mButton = (Button)findViewById(R.id.button1);
mButton.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable drawable = (AnimationDrawable)mButton.getBackground();
drawable.start();

注意帧动画容易引起OOM。

三、属性动画

属性动画从 API 11 才有,属性动画可以对任意对象的属性进行动画而不仅仅是View,达到的效果是:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。属性动画常用的动画类:ValueAnimator、ObjectAnimator、AnimatorSet。ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。
属性动画也有对应的xml标签,但是建议使用代码来实现属性动画,因为使用代码比xml简单。而且很多时候一个属性的起始值无法提前确定。

1、通过几个例子看如何使用属性动画:

  1. 改变对象myObject的translationY属性,让其沿着Y轴向上平移一段距离:它的高度。该动画在默认时间内完成
ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();
  1. 改变一个对象的背景色属性,让背景色在3秒内从 0xFFFF8080 到 0xFF8080FF 的渐变,动画会无限循环而且会有反转效果
ValueAnimator anim = ObjectAnimator.ofInt(myObject, "backgroundColor",0xFFFF8080,0xFF8080FF);
anim.setDuration(3000);
anim.setEvaluator(new ArgbEvaluator());
anim.setRepeatCount(ValueAnimator.INFINITE);
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.start();
  1. 动画集合,5秒内对View的旋转,平移,缩放和透明都进行改变。
AnimatorSet set = new AnimatorSet();
set.playTogether(
        ObjectAnimator.ofFloat(myView, "rotationX", 0, 360),
        ObjectAnimator.ofFloat(myView, "rotationY", 0, 180),
        ObjectAnimator.ofFloat(myView, "rotation", 0, -90),
        ObjectAnimator.ofFloat(myView, "translationX", 0, 90),
        ObjectAnimator.ofFloat(myView, "translationY", 0, 90),
        ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f),
        ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f),
        ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1)
);
set.setDuration(5*1000).start();

2、上面的代码总结

上面代码用到一个主要的方法
ObjectAnimator.ofFloat(target, propertyName, values...);

target 是动画目标,任何对象,不一定必须是View
propertyName 是属性名字
values 是可变参数, 从v1变化到v2到vn。。。

例子:
mIv是一个imageView
//alpha 从0 到1 的动画
ObjectAnimator.ofFloat(mIv, "alpha", 0f,1f)
.setDuration(500)
.start();
如果要实现其他效果,修改propertyName和values就行了。

属性动画的原理就是通过反射,以动画的效果多次调用set方法来改变属性值的。所以,使用属性动画时,相应的对象属性必须有set方法,get方法可以没有,但是如果使用动画的时候没有传递初始值,就必须提供get方法,因为系统要通过get方法获取属性的默认初始值。

在属性动画中,View的常用属性

alpha 透明度
rotation z轴旋转
rotationX x轴旋转
rotationY y轴旋转
translationX x水平偏移
translationY y水平偏移
ScaleX x轴缩放
ScaleY y轴缩放

3、插值器和估值器

插值器(TimeInterpolator/Interpolator)用来修饰动画效果,定义动画的变化规率(变化趋势),比如平移动画,可以匀速平移也可以加速平移,这个由插值器决定。
估值器(Evaluator)用来决定具体的数值变化,比如(匀)加速平移时,“加速度”是多少由估值器决定。

插值器TimeInterpolator和Interpolator,后者是继承前者的接口。
TimeInterpolator接口是属性动画中新增的,用于兼容Interpolator接口,这使得所有过去的Interpolator实现类都可以直接在属性动画使用。
出自:http://blog.csdn.net/carson_ho/article/details/72863901

系统内置的插值器有以下几种:
  • AccelerateInterpolator 加速
  • DecelerateInterpolator 减速
  • LinearInterpolator 匀速
  • AccelerateDecelerateInterpolator 先加速再减速(在动画开始与结束的地方速率改变比较慢,在中间的时候最快)
  • AnticipateInterpolator 开始的时候向后然后向前甩(先退后再加速前进)
  • AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值(先退后再加速前进,超出终点后再回终点)
  • BounceInterpolator 动画结束的时候弹起(最后阶段弹球效果)
  • CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
  • OvershootInterpolator 向前甩一定值后再回到原来位置(快速完成动画,超出再回到结束时的位置)
    以上每种插值器都有对应的xml资源,比如:@android:anim/linear_interpolator。(注意资源名的规律)
系统内置的估值器有以下三种:

IntEvaluator 以整型的形式从初始值到结束值 进行过渡
FloatEvaluator 以浮点型的形式从初始值到结束值 进行过渡
ArgbEvaluator 以Argb类型的形式从初始值到结束值 进行过渡

如果系统内置的插值器和估值器无法满足需求,也可以自定义。
View动画的插值器实现Interpolator接口,View动画没有估值器
属性动画的插值器实现实现TimeInterpolator接口,估值器实现TypeEvaluator接口
自定义插值器和估值器参考系统内置的插值器和估值器即可。

以下摘自http://blog.csdn.net/carson_ho/article/details/72863901
实现Interpolator接口自定义插值器的说明(TimeInterpolator接口相同)

public interface Interpolator {
    // 内部只有一个方法
    float getInterpolation(float input) {
       // 参数说明
       // input值值变化范围是0-1,且随着动画进度(0% - 100% )均匀变化
       // 即动画开始时,input值 = 0;动画结束时input = 1
       // 而中间的值则是随着动画的进度(0% - 100%)在0到1之间均匀增加

       ...// 插值器的计算逻辑

       return xxx;
       // 返回的值就是用于估值器继续计算的fraction值
    }
}  

实现TypeEvaluator接口自定义估值器的说明

public interface TypeEvaluator {  

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        // 参数说明
        // fraction:插值器getInterpolation()的返回值
        // startValue:动画的初始值
        // endValue:动画的结束值

        ....// 估值器的计算逻辑

        return xxx;
        // 赋给动画属性的具体数值
        // 使用反射机制改变属性变化

        // 特别注意
        // 插值器的input值 和 估值器fraction有什么关系呢?
        // 答:input的值决定了fraction的值:input值经过计算后传入到插值器的getInterpolation()
        // 然后通过实现getInterpolation()中的逻辑算法,根据input值来计算出一个返回值,而这个返回值就是fraction了
    }
}  
如何使用插值器和估值器

View动画和属性动画都可以使用插值器,估值器只有属性动画可以用。

插值器用法

// 步骤1:创建需要设置动画的视图View
Button mButton = (Button) findViewById(R.id.Button);
// 步骤2:创建透明度动画的对象 & 设置动画效果
Animation alphaAnimation = new AlphaAnimation(1,0);
alphaAnimation.setDuration(3000);
// 步骤3:创建对应的插值器类对象
Interpolator overshootInterpolator = new OvershootInterpolator();
// 步骤4:给动画设置插值器
alphaAnimation.setInterpolator(overshootInterpolator);
// 步骤5:播放动画
mButton.startAnimation(alphaAnimation);

估值器用法

// 在第3个参数中传入对应估值器类的对象
ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new Evaluator(),1,3);

4、属性动画的监听

有两个监听接口AnimatorListener和AnimatorUpdateListener。AnimatorListener和View动画的AnimationListener类似,可以监听动画的开始、结束等过程。AnimatorUpdateListener可以监听动画的每一帧变化,动画每变化一帧,接口里的方法被调用一次。

四、动画相关的其他问题、知识、技巧

对于没有set和get方法的对象如何使用属性动画:
  1. 给对象加上相应的set和get方法,如果有权限的话(对系统的View是没有权限改源码的)
  2. 用一个包装类包装原始对象,间接的提供set和get方法
  3. 使用ValueAnimator,监听动画过程,自己实现属性的改变。ValueAnimator本身不作用于任何对象,直接使用它是没有效果的。它可以对一个值做动画,可以监听其动画过程,在动画过程中自己实现修改对象的属性值,也就相当于对象做了动画,示例代码如下:
private void performAnimate(final View button, final int start, final int end) {

    ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);

    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        //持有一个IntEvaluator对象,方便下面估值的时候使用
        private IntEvaluator mIntEvaluator = new IntEvaluator();

        @Override
        public void onAnimationUpdate(ValueAnimator animator) {
            //获得当前动画的进度值,整型1-100之间
            int currentValue = (int) animator.getAnimatedValue();

            //获得当前进度占整个动画过程的比例,浮点型,0-1之间
            float fraction = animator.getAnimatedFraction();
            //直接调用整型估值器,通过比例计算出宽度,然后设给Button
            button.getLayoutParams().width = mIntEvaluator.evaluate(fraction, start, end);
            button.requestLayout();
        }
    });
    valueAnimator.setDuration(5000).start();
}

@Override
public void onClick(View v) {
    if (v == mButton) {
        performAnimate(mButton, mButton.getWidth(), 500);
    }
}
通过源码可以看出,属性动画需要运行在有Looper的线程中
使用动画的注意事项
  1. OOM问题。主要是帧动画图片数量较多且图片较大时容易出现OOM。
  2. 内存泄漏。在属性动画中有一类无限循环的动画,这类动画需要在Activity退出时及时停止,否则将导致Activity无法释放从而造成内存泄漏。通过验证后发现View动画不存在此问题。
  3. 兼容性问题。动画在3.0以下的系统上有兼容性问题,需要做好适配。
  4. View动画问题。View动画是对View的影像做动画,并不会真正的改变View的状态。如果出现动画完成后View无法隐藏,即setVisibility(View.GONE)失效,这个时候只要调用view.clearAnimation()清除View动画即可解决。
  5. 不要使用px。尽量使用dp,使用px会导致在不同设备上有不同的效果。
  6. View平移后:在3.0以前的系统,View动画和属性动画都是新位置无法点击,老位置可以点击;3.0以后(包括3.0),属性动画的点击事件触发位置是位移后的位置,View动画是原位置。
  7. 开启硬件加速可以提高动画的流畅性。

五、补充属性动画

View动画可以设置ViewGroup的子View的出场动画,属性动画可以为ViewGroup的子View的显示和隐藏设置过渡动画。出场动画文中已经介绍,属性动画实现的过度动画详细见ForeverCy的文章Android中的View动画和属性动画 中的相关部分。

Android中的动画总结的更多相关文章

  1. Android中矢量动画

    Android中矢量动画 Android中用<path> 标签来创建SVG,就好比控制着一支画笔,从一点到一点,动一条线. <path> 标签 支持一下属性 M = (Mx, ...

  2. Android中的动画

    Android中的动画分为: 1.逐帧动画(Frame Animation):  把动画过程的每张静态图片都收集起来,然后由Android来控制依次显示这些静态图片,然后利用人眼”视觉暂留“的原理,给 ...

  3. Android中的动画具体解释系列【4】——Activity之间切换动画

    前面介绍了Android中的逐帧动画和补间动画,并实现了简单的自己定义动画.这一篇我们来看看怎样将Android中的动画运用到实际开发中的一个场景--Activity之间跳转动画. 一.定义动画资源 ...

  4. Android中的动画详解系列【4】——Activity之间切换动画

    前面介绍了Android中的逐帧动画和补间动画,并实现了简单的自定义动画,这一篇我们来看看如何将Android中的动画运用到实际开发中的一个场景--Activity之间跳转动画. 一.定义动画资源 如 ...

  5. 初识android中的动画

    动画效果可以大大提高界面的交互效果,因此,动画在移动开发中的应用场景较为普遍.掌握基本的动画效果在成熟的软件开发中不可或缺.除此之外,用户对于动画的接受程度远高于文字和图片,利用动画效果可以加深用户对 ...

  6. Android中的动画机制

          1 逐帧动画   逐帧动画 就是一系列的图片按照一定的顺序展示的过程.   逐帧动画很简单, 只需要在drawable中或者anim中定义一个Animation-list 其中包含多个it ...

  7. Android中的动画效果

    动画的种类 透明动画alphaAnimation 在代码中配置动画: findViewById(R.id.btnAnimMe).setOnClickListener(new View.OnClickL ...

  8. Android中的动画学习总结

    android中动画可分为三种:帧动画,补间动画,和属性动画.其中属性动画是google推荐的,它可以实现前面两种动画的效果,运用起来更加灵活. 帧动画:顾名思义,就是一帧一帧的图片,快速播放形成的动 ...

  9. Android(java)学习笔记200:Android中View动画之 XML实现 和 代码实现

    1.Animation 动画类型 Android的animation由四种类型组成: XML中: alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动 ...

  10. Android中的动画,选择器,样式和主题的使用

    一.动画: 1.动画的分类: 1).Tween动画:这种实现方式可以使视图组件移动.放大.缩小以及产生透明度的变化: 2).Frame动画:传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影. ...

随机推荐

  1. Developing for nRF52810(转载)

    Table of Contents Introduction Hardware emulation of nRF52810 Limitations Software emulation of nRF5 ...

  2. poj1523赤裸裸的割点

    这题真是没什么好说的...赤裸裸的求割点直接模板上 #include<cstdio> #include<cstring> #include<iostream> #i ...

  3. [转] 对 forEach(),map(),filter(),reduce(),find(),every(),some()的理解

    1.forEach() 用法:array.forEach(function(item,index){}) 没有返回值,只是单纯的遍历 2.map() 用法:array.map(function(ite ...

  4. luogu1578 奶牛浴场 枚举点最大子矩阵

    建议看看王知昆dalao的论文,讲得很好 #include <algorithm> #include <iostream> #include <cstring> # ...

  5. Clickonce - Change deployment URL after publish

    mage.exe -Update C:\inetpub\wwwroot\aspnet40\AminoScience\Uploads\Application Files\AccUFeed_1_0_0_5 ...

  6. python week08 并发编程之多进程--实践部分

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  7. linuxlinux0.11源码学习——bootsect.s学习

    由于一直想写一个自己的操作系统,网上推荐了<linux内核完全注释>.自学了一个星期,感觉这本书还是很好的,同时写下关于内核代码的理解,如果有什么不对的对方,欢迎大家一起来交流. 在内核引 ...

  8. 开发者工具删除元素Delete Element

    开发者工具有个很好用的功能,通过删除元素,可以查看页面哪些元素比较特殊,同时也可以排除干扰.

  9. 快速samba配置

      apt-get install samba   smbpasswd -a user 如果需要写权限 [homes] read only = no

  10. Multiset ------ 多重集合

    Multiset的中文名是多重集合,其实就是集合的扩展版.唯一的不同是集合中一个值只能出现一次,而多重集合中一个值可以出现多次. 粗略看了看MSDN,在STL中,multiset和set的成员函数声明 ...