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. 硬件加速

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