View动画

View动画的种类

  • View动画的四种变化:平移动画,缩放动画,旋转动画和透明度动画。这四种变化对应着Animation的四个子类分别是TranslateAnimation,ScaleAnimation,RotateAnimation和AlphaAnimation。对于View动画来说,建议采用XML来定义,可读性更好

  • 要使用View动画,首先要创建动画的XML文件,这个文件的路径为:res/anim/filename.xml。View动画是有固定语法的:

    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
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"//插值器,影响动画的速度,这个是默认值
    android:shareInterpolator="true"//表示集合中动画是否和集合共用一个插值器
    >
    <alpha
    android:fromAlpha="1.0"//表示透明度起始值
    android:toAlpha="1.0"//表示透明度结束值
    />
    <scale
    android:fromXScale="0.0"//水平方向缩放起始值
    android:toXScale="1.0"//水平方向缩放结束值
    android:fromYScale="0.0"//竖直方向缩放起始值
    android:toYScale="1.0"//竖直方向缩放结束值
    android:pivotX="float"//缩放的轴点X坐标会影响缩放效果
    android:pivotY="float"/>//缩放的轴点Y坐标会影响缩放效果
    //轴点默认为中心点
    <translate
    android:fromYDelta="0.0"//Y起始值
    android:fromXDelta="0.0"//X起始值
    android:toXDelta="1.0"//X结束值
    android:toYDelta="1.0"/>//Y结束值
    <rotate
    android:fromDegrees="0"//旋转开始的角度
    android:toDegrees="180"//旋转结束的角度
    android:pivotY="float"//旋转轴点的x坐标
    android:pivotX="float"/>//旋转轴点的y坐标


    </set>

android:duration//动画持续时间

android:fillAfter//动画结束以后View是否留在结束位置,true停留false不停

  • 如何应用动画

    1
    2
    3
    Button button=(Button) findViewById(R.id.button1);
    Animation animation=AnimationUtils.loadAnimation(this,R.anim.animation_test);
    button.startAnimation(animation);

帧动画

  • 帧动画是顺序播放一组预先定义好的图片类似于电影播放。使用AnimationDrawable来使用帧动画。

  • 用法:

    1. 先定义一个AnimationDrawable

      1
      2
      3
      4
      5
      6
      7
      <?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/avatar1" android:duration="500"/>
      <item android:drawable="@drawable/avatar2" android:duration="500"/>
      <item android:drawable="@drawable/avatar3" android:duration="500"/>
      </animation-list>
    2. 调用

      1
      2
      3
      binding.button1.setBackgroundResource(R.drawable.frame_animation);
      AnimationdDrawable drawable=(AnimationdDrawable) binding.button1.getBackground();
      drawable.start();

      尽量避免使用过多尺寸较大的图片不然容易引起OOM

    View动画的特殊使用场景

    LayoutAnimation

    • 这个作用于ViewGroup,为其指定一个动画,这样当他的子元素出厂时都会具备这种效果,这种效果常常被用在ListView上面

    • 实现步骤

      1. 定义LayoutAnimation

        1
        2
        3
        4
        5
        6
        7
        8
        //res/anim/anim_layout.xml
        <layoutAnimation
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:delay="0.5"
        android:animationOrder="normal"
        android:animation="@anim/anim_item" />


      2. 为子元素指定出场动画

        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
        <?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_decelerate_interpolator"
        android:shareInterpolator="true"
        >
        <alpha
        android:fromAlpha="1.0"
        android:toAlpha="1.0"
        />
        <scale
        android:fromXScale="0.0"
        android:toXScale="1.0"
        android:fromYScale="0.0"
        android:toYScale="1.0"
        android:pivotX="float"
        android:pivotY="float"/>
        <translate
        android:fromYDelta="0.0"
        android:fromXDelta="0.0"
        android:toXDelta="1.0"
        android:toYDelta="1.0"/>
        <rotate
        android:fromDegrees="0"
        android:toDegrees="180"
        android:pivotY="float"
        android:pivotX="float"/>
        </set>
      3. 为ViewGroup指定android:layoutAnimation属性

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/anim_layout"
        ......
        ......
        ......
        />

Activity的切换方式

  • Activity有默认的切换效果,但是这个效果我们可以自定义,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity或者finish之后调用才可以生效它的参数含义:

    1. enterAnim,Activity被打开时所需要的动画资源id
    2. exitAnim,Activity被暂停时所需要的动画资源id
  • 实现:

    1. 启动

      1
      2
      3
      Intent intent=new Intent(this,TestActivity.class);
      startActivity(intent);
      overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
    2. 退出

      1
      2
      3
      4
      5
      @Override
      public void finish(){
      super.finish();
      overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
      }

使用属性动画

  • ValueAnimator

    1
    2
    3
    4
    5
    6
    ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", /*Red*/0xFFFF8080, /*Blue*/0xFF8080FF);
    colorAnim.setDuration(3000);
    colorAnim.setEvaluator(new ArgbEvaluator());
    colorAnim.setRepeatCount(ValueAnimator.INFINITE); // 无限循环
    colorAnim.setRepeatMode(ValueAnimator.REVERSE); // 反转效果
    colorAnim.start();
  • ObjectAnimator

    1
    ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();//负数代表向上移动
  • AnimatorSet

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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();

使用动画的注意事项

  1. OOM 问题

    主要发生在帧动画里,图片数量多且图片较大时就容易出现这种情况,在实际开发中应尽量避免使用复杂的帧动画。

  2. 内存泄漏

    属性动画中的无限循环动画。这类动画需要在Activity退出时及时停止不然会造成内存泄漏。必须在 onPause() 或 onDestroy() 中调用 anim.cancel() 停止动画。

  3. 兼容性问题

    动画在 Android 3.0 (API 11) 以下的系统上可能存在无法正常工作的情况,需做好适配。

  4. View动画的问题

    View 动画只是影像的改变,不是真正改变 View 的状态。有时候动画完成后,调用 setVisibility(View.GONE) 可能失效。这个时候只要调用view.clearAnimation()清除View动画即可解决

  5. 不要使用px

    动画中尽量不要使用px,尽量用dp

  6. 动画元素的交互

    这是 View 动画 与 属性动画 的本质区别:

    • View 动画: 移动后,点击事件仍在原位。视觉在 A 点,点击响应还在起始点。
    • 属性动画: 从 Android 3.0 开始,属性动画移动后,点击事件随之移动。视觉在 B 点,点击响应也在 B 点。
  7. 硬件加速

    建议使用动画时开启硬件加速,这能显著提高动画的流畅度,减少卡顿。