AndroidView动画相关总结

Android 中的动画可以分为三种 : View 动画、帧动画和属性动画

  • View 动画:包含平移、缩放、旋转、透明度等渐近式动画,同时支持自定义动画。
  • 帧动画:主要通过顺序播放一系列图片,可理解为图片切换动画(如果图片过多过大会导致 OOM)
  • 属性动画:动态改变对象的属性来达到动画效果(属性动画为 API 11 新特性,低版本中无法直接使用,可使用动画兼容库 nineoldandroids 来使用它)

View 动画

View 动画可以分4类:

  • TranslateAnimation 平移动画,标签:,主要作用:移动View
  • ScaleAnimation 缩放动画,标签:,主要作用:放大或缩小View
  • RotateAnimation 旋转动画,标签:,主要作用:旋转View
  • AlphaAnimation 透明的动画,标签:,主要作用:改变View的透明度

使用示例:

  • 创建xml,例如: 新建 res/anim/filename.xml 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    //动画插值器,影响动画的播放速度
    android:interpolator="@android:anim/accelerate_interpolator"
    //表示集合中的动画是否和集合共享一个插值器
    android:shareInterpolator="true" >
    //透明度动画,对应 AlphaAnimation 类,可以改变 View 的透明度
    <alpha
    android:duration="3000"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />
    //旋转动画,对应着 RotateAnimation ,它可以使 View 具有旋转的动画效果
    <rotate
    android:duration="2000"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:startOffset="3000"
    android:toDegrees="180" />
    <!--通过设置第一个alpha动画播放3s后启动rotate动画实现组合动画,如果不设置startOffset则同时播放
    pivotX:表示旋转时候的相对轴的坐标点,即围绕哪一点进行旋转,默认情况下轴点是 View 中心
    -->
    //平移动画,对应 TranslateAnimation 类,可以使 View 完成垂直或者水平方向的移动效果。
    <translate
    android:fromXDelta="500"
    android:toXDelta="0" />
    //缩放动画,对应 ScaleAnimation 类,可以使 View 具有放大和缩小的动画效果。
    <scale
    android:duration="1000"
    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="50"
    android:pivotY="50"
    android:toXScale="2"
    android:toYScale="2" />
    </set>

    解释:

  • 标签表示动画集合,对应 Animationset 类,可表示若干个动画,并且它的内部也可以嵌套其他动画集合。它还包含以下两个属性;

    • android:interpopator 表示动画集合所采用的插值器,插值器影响动画的播放速度,比如实现非匀速动画效果,这个属性可以不指定,默认为 android:interpolator=”@android:anim/accelerate_decelerate_interpolator”,即加速减速插值器。
    • android:shareInterpolator 表示集合中的动画是否和集合共享一个插值器,如果集合不指定插值器,那么子动画就需要单独指定所需要的插值器或者使用默认值。
  • android:fillAfter 表示动画结束以后, View 是否停留在结束动画的位置,如果为 false , View 会回到动画开始的位置。(注:fillAfter是指动画结束时画面停留在最后一帧,这个参数不能在 ,,, 中设置,这是没有作用的,必须通过以下方式设置:在动画 XML 文件的 节点中设置:在程序 Java 代码中进行设置:setFillAfter(true)。)
    代码中使用动画:

  • 使用 xml 文件的动画:(如下图:透明渐变动画)

    1
    2
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
    view.startAnimation(animation);
  • Java 代码实现动画:

    1
    2
    3
    4
    5
    6
    //创建一个透明度渐变动画,在 2000ms 内,将 VIew 的透明度由 0.1f 变为 1.0f 
    AlphaAnimation alphaAnimation=new AlphaAnimation(0.1f,1.0f);
    alphaAnimation.setDuration(2000);
    alphaAnimation.setRepeatCount(4);
    alphaAnimation.setRepeatMode(Animation.REVERSE);
    view.startAnimation(alphaAnimation);

    注:还可以通过setAnimationListener给View添加过程监听:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static interface AnimationListener {
    //监听动画开始
    void onAnimationStart(Animation animation);
    //监听动画结束
    void onAnimationEnd(Animation animation);
    //动画取消
    void onAnimationCancel(Animator animation);
    //监听动画重复
    void onAnimationRepeat(Animation animation);
    }
    1
    2
    3
    4
    public static interface AnimatorUpdateListener {
    //监听整个动画过程,动画是由许多帧组成,动画每播放一帧,该方法就会调用一次
    void onAnimationUpdate(ValueAnimator animation);
    }
  • 自定义 View 动画:

    • 自定义新的动画需要继承 Animation 这个抽象类
    • 重写 inatialize 和 applyTransformation 这两个方法
    • initialize 方法可做一些初始化工作,在 Transformation 方法中进行矩阵变换,很多时候采用 Camera 来简化矩阵的变换过程
    • 可参考 Android 的 APIDemos 中的自定义动画 Rotate3dAnimation 的例子学习,这是一个可以围绕 Y 轴旋转并同时沿着 Z 轴平移从而实现类似一种 3D 效果的动画。

帧动画

系统提供了AnimationDrawble来使用帧动画,可通过 XML 定义一个 AnimationDrawble

  • xml创建动画示例如下:(创建文件:\res\anim\frame_animation_list.xml)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?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/img1"
    android:duration="200"/>
    <item
    android:drawable="@drawable/img2"
    android:duration="200"/>
    <item
    android:drawable="@drawable/img3"
    android:duration="200"/>
    <!--<item-->
    <!--android:drawable="@drawable/img4"-->
    <!--android:duration="300"/>-->
    <!--<item-->
    <!--android:drawable="@drawable/img5"-->
    <!--android:duration="400"/>-->
    </animation-list>
  • 使用帧动画示例:
    1
    2
    3
    4
    //将图片设置成背景图片
    view.setBackgroundResource(R.drawable.frame_animation_list);
    AnimationDrawable frameAnimation = (AnimationDrawable) view.getBackground();
    frameAnimation.start();

注意:帧动画使用简单,但需要避免使用大图导致OOM

属性动画

  • 属性动画可以对任意对象的属性做动画,而不仅仅是 View 对象
  • 动画默认时间间隔是 300ms ,默认帧率是 10ms/帧
  • 属性动画是从 API 11 出来的,可使用动画兼容库 nineoldandroids来兼容以前版本,在 API 11 以前其内部是通过代理 View 动画来实现的
  • 比较常见的几个动画类:ValueAnimator、ObjectAnimator 和 AnimatorSet ,其中 ObjectAnimator 继承自 ValueAnimator ,AnimatorSet 是动画集合,可以定义一组动画

示例代码:

  • 改变一个对象 TranslationY 属性,让其沿 Y 轴平移一段距离
    1
    2
    3
    4
    5
    6
    private void translateViewByObjectAnimator(View targetView){
    //TranslationY 目标 View 要改变的属性
    //targetView.getHeight() 要移动的距离
    ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(targetView,"TranslationY",targetView.getHeight());
    objectAnimator.start();
    }
  • 改变一个对象的背景色属性,实现改变一个 View 的背景色
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private void changeViewBackGroundColor(View targetView){
    ValueAnimator valueAnimator=ObjectAnimator.ofInt(targetView,"backgroundColor", Color.RED,Color.BLUE);
    valueAnimator.setDuration(3000);
    //设置估值器,该处插入颜色估值器
    valueAnimator.setEvaluator(new ArgbEvaluator());
    //无限循环
    valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    //翻转模式
    valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
    valueAnimator.start();
    }
  • 动画集合,5 秒内对 View 旋转、平移、缩放和透明度进行了改变
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    private void startAnimationSet(View targetView){
    AnimatorSet animatorSet=new AnimatorSet();
    animatorSet.playTogether(ObjectAnimator.ofFloat(targetView,"rotationX",0,360),
    //旋转
    ObjectAnimator.ofFloat(targetView,"rotationY",0,360),
    ObjectAnimator.ofFloat(targetView,"rotation",0,-90),
    //平移
    ObjectAnimator.ofFloat(targetView,"translationX",0,90),
    ObjectAnimator.ofFloat(targetView,"translationY",0,90),
    //缩放
    ObjectAnimator.ofFloat(targetView,"scaleX",1,1.5f),
    ObjectAnimator.ofFloat(targetView,"scaleY",1,1.5f),
    //透明度
    ObjectAnimator.ofFloat(targetView,"alpha",1,0.25f,1));
    animatorSet.setDuration(3000).start();
    }
  • 通过xml 实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <?xml version="1.0" encoding="utf-8"?><!--set 标签对应着 AnimatorSet-->
    <set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
    <!--对应着 ObjectAnimator-->
    <objectAnimator
    android:propertyName="x"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:startOffset="10"
    android:valueTo="300"
    android:valueType="floatType" />
    <!--其中propertyName 属性设置为translationX ,valueType 设置为floatType 可以正常启动
    如果 valueType 设置为 intType 将报错,即属性类型必须为 floatType 类型,并且android:propertyName="translationX" 表示移动 300 ,而 android:propertyName="x"表示移动到300 ,是两个不同属性-->
    <!--startOffset 指定延迟多久开始播放动画-->
    <!--valueType 表示指定的 android:propertyName 所指定属性的类型,intType 表示指定属性是整型的,
    如果指定属性为颜色,那么不需要指定 valueType 属性,系统会自动处理
    repeatCount 表示动画循环次数,默认值为0,-1 表示无限循环-->
    <objectAnimator
    android:propertyName="y"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:startOffset="10"
    android:valueTo="300"
    android:valueType="floatType" />
    <!--对应着 ValueAnimator-->
    <!--<animator-->
    <!--android:propertyName="rotation"-->
    <!--android:duration="300"-->
    <!--android:valueFrom="0"-->
    <!--android:valueTo="360"-->
    <!--android:startOffset="10"-->
    <!--android:repeatCount="infinite"-->
    <!--android:repeatMode="reverse"-->
    <!--android:valueType="intType"/>-->
    </set>

View 动画的特殊场景

  • 在 ViewGroup 中控制子元素的出场效果,如:LayoutAnimation

    • 定义 LayoutAnimation res/anim/layout_animation.xml
      • android:delay 表示子元素开始动画的延时时间,(取值为子元素入场动画时间 duration 的倍数,比如子元素入场动画时间为 300ms ,那么 0.5 表示每个子元素都需要延迟 150ms 才能播放入场动画,即第一个子元素延迟 150ms 开始播放入场动画,第二个子元素延迟 300ms 开始播放入场动画,依次类推进行。)
      • android:animationOrder 表示子元素动画的开场顺序,normal(正序)、reverse(倒序)、random(随机)。
      • android:animation 表示为子元素指定具体的动画效果,例如代码中 “@anim/zoom_in’ 是我们自己定义的一个 XML 动画。
        1
        2
        3
        4
        5
        6
        <?xml version="1.0" encoding="utf-8"?>
        <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:delay="0.5"
        android:animationOrder="normal"
        android:animation="@anim/zoom_in">
        </layoutAnimation>
    • 定义 res\anim\zoom_in.xml 动画
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
      <alpha
      android:duration="1000"
      android:fromAlpha="0.1"
      android:toAlpha="1.0"/>
      <scale
      android:pivotY="50%"
      android:pivotX="50%"
      android:fromYScale="0.1"
      android:toYScale="1.0"
      android:duration="1000"
      android:fromXScale="0.1"
      android:toXScale="1.0"/>
      </set>
    • 使用LayoutAnimation动画
      • xml直接使用 android:layoutAnimation=”@anim/layout_animation”
        1
        2
        3
        4
        5
        6
        <ListView
        android:layoutAnimation="@anim/layout_animation"
        android:id="@+id/lv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        </ListView>
        • java 代码中直接使用,通过LayoutAnimationController来实现
          1
          2
          3
          4
          5
          //用于控制子 view 动画效果
          LayoutAnimationController layoutAnimationController= new LayoutAnimationController(AnimationUtils.loadAnimation(this,R.anim.zoom_in));
          layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
          listView.setLayoutAnimation(layoutAnimationController);
          listView.startLayoutAnimation();
  • 在 Activity 中可以实现不同 Activity 之间的切换效果。(主要使用:overridePenddingTransation(int enterAnim,int exitAnim))

    1
    2
    3
    4
    overridePendingTransition(R.anim.in, R.anim.out);
    // 注意:该方法必须要在 startActivity(intent) 和 finish() 方法之后调用才会有效
    //enterAnim: Activity 打开时所需动画的资源 id 。
    //exitAnim: Acitivty 退出时所需动画的资源 id 。

    注:Fragment 也可以添加切换动画,通过 FragmentTransation 中的 setCustomAnimations() 方法来实现切换动画,这个动画需要的是 View 动画,不能使用属性动画。

其他

  • 插值器和估值器

    • Timeinterpolator:时间插值器,是一个接口类,根据属性改变百分比计算改变后的属性值,系统自带:
      • LinearInterpolator (线性时间插值器,匀速动画)
      • AccelerateDecelerateInterpolater(加速减速插值器,动画两头慢,中间快)
      • DecelerateInterpolater (减速插值器,动画越来越慢)
    • TypeEvaluator: 类型估值算法,也叫估值器,是一个接口类,作用同上
      • 系统自带有 IntEvaluator(针对整型属性)
      • FloatAvaluator(浮点型属性)
      • ArgbEvaluator(针对 Color 属性)
  • 对任意属性做动画,如:

    1
    2
    3
    4
    5
    private void performAnimation(View button){
    ObjectAnimator.ofInt(button,"width",500)
    .setDuration(200)
    .start();
    }

参考