Android Animation梳理

Android 中动画分为早期的 Animation (视图动画) 和 Android 3.0 增加的 Animator (属性动画)。这里主要记录 Animation 的使用方法。

一、Animation

Animation

二、FrameAnimation (逐帧动画)

FrameAnimation 就是通过逐帧播放来实现的动画。

逐帧动画示例

使用步骤:

  1. res/drawable 文件夹下新建 animation-listXML;
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <!-- animation-list 帧动画 -->
    <!-- android:oneshot的值为 false代表播放多次,true代表只播放一次 -->
    <!-- duration代表每张图片的播放时间 ,定义一个持续时间为50毫秒的动画帧 -->
    <item
        android:drawable="@drawable/loading_1"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_2"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_3"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_4"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_5"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_6"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_7"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_8"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_9"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_10"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_11"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_12"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_13"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_14"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_15"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_16"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_17"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_18"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_19"
        android:duration="50" />
    <item
        android:drawable="@drawable/loading_20"
        android:duration="50" />

</animation-list>
  1. 添加控件,设置 background;

直接在 XML 中声明背景图片:

<ImageView
        android:id="@+id/iv_loading"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/loading_anim_layout"/>

也可以动态设置背景图片:

mIvLoading = findViewById(R.id.iv_loading);
        AnimationDrawable animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.loading_anim_layout);
        mIvLoading.setBackground(animationDrawable);
  1. 开启和关闭帧动画;
    设置完背景图片后,需要调用动画启动的函数,不然默认只会停留在第一帧处。
    如:
((AnimationDrawable)mIvLoading.getBackground()).start();
//stop() 停止播放
  1. 第一步中设置帧也可以直接在代码中添加;
private void setFrameAnimation() {
        AnimationDrawable animationDrawable = new AnimationDrawable();
        //为AnimationDrawable添加动画帧
        animationDrawable.addFrame(getResources().getDrawable(R.drawable.loading_1), 50);
        animationDrawable.addFrame(getResources().getDrawable(R.drawable.loading_2), 50);
        animationDrawable.addFrame(getResources().getDrawable(R.drawable.loading_3), 50);
        animationDrawable.addFrame(getResources().getDrawable(R.drawable.loading_4), 50);
        //...
        // 设置为循环播放  
        animationDrawable.setOneShot(true);
        mIvLoading.setBackground(animationDrawable);
    }

三、TweenAnimation 补间动画

Tween 动画是通过对 View 进行一些列的图像变换,包括平移、缩放、旋转、透明度变化,从而达到动画效果。
Tween 动画并不改变 View 的属性,只是改变了 View 绘制的位置,没有改变 View 对象本身。比如屏幕左上角的一个空间,通过补间动画平移到右上角后,其点击区域还是在左上角。

实现补帧动画有两种方式,XML 中声明和直接代码两种方式。

(1) AlphaAnimation(透明度)

  1. XML 方式实现:
    res/anim/ 目录下添加 XML 文件
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="false"
    android:fromAlpha="1.0"
    android:toAlpha="0.0" />
  • fromAlpha : 开始时透明度,0 是完全透明,1 是完全不透明;
  • toAlpha : 结束时透明度,0 是完全透明,1 是完全不透明;
  • duration : 动画持续时间,单位毫秒;
  • fillAfter :动画结束后是否停留在最后一帧。默认 false
  • fillBefore :动画结束后是否停留在第一帧。默认 true。和 fillAfter同时设置则只会看 fillAfter
  • fillEnbabled : 与 android:fillBefore 效果相同?
  • interpolator : 指定插值器

获取动画并设置给对应的 View

Animation alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_alpha);
        mIvLoading.startAnimation(alphaAnimation);
  1. 代码实现方式:
Animation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
        alphaAnimation.setDuration(500);//设置动画持续时间为500毫秒
        alphaAnimation.setFillAfter(false);//设置动画结束后保持当前的位置(即不返回到动画开始前的位置)
        mIvLoading.startAnimation(alphaAnimation);

(2) ScaleAnimation(缩放)

  1. XML 实现方式:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:toXScale="1.0"
    android:toYScale="1.0" />
  • fromXScalefromYScale : 动画开始前X,Y的缩放,0.0 为不显示,1.0 为正常大小;
  • toXScaletoYScale: 动画最终缩放的倍数, 1.0 为正常大小,大于 1.0 放大,小于 1.0 缩小;

还可以设置:

  • pivotXpivotY : 动画起始位置,相对于自身的百分比,两个都为 50% 表示动画从自身中间开始;
  • repeatCount : 动画重复的计数,动画将会执行该值 +1 次;
  • repeatMode : 动画重复的模式,reverse 为反向,当第偶次执行时,动画方向会相反。restart 为重新执行,方向不变;
  • startOffset : 动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒;
  • fromXDelta, fromYDelta : 起始时 XY 座标;
  • toXDeltatoYDelta : 动画结束时 X, Y 的座标;

获取动画并设置给对应的 View

Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_scale);
        mIvLoading.startAnimation(scaleAnimation);
  1. 代码实现方式:
Animation scaleAnimation = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(1000);
        scaleAnimation.setRepeatCount(3);//设置动画循环次数
        scaleAnimation.setRepeatMode(Animation.REVERSE);
        scaleAnimation.setStartOffset(0);
        scaleAnimation.setInterpolator(this, android.R.anim.decelerate_interpolator);//设置动画插入器
        mIvLoading.startAnimation(scaleAnimation);

(3) RotateAnimation(旋转)

  1. XML 实现方式:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360" />
  • fromDegrees : 动画开始时的角度;
  • toDegrees : 动画结束时的角度,为正顺时针旋转,为负逆时针旋转;

获取动画并设置给对应的 View

Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_rotate);
        mIvLoading.startAnimation(rotateAnimation);
  1. 代码实现方式:
Animation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotateAnimation.setDuration(1000);
        rotateAnimation.setFillAfter(true);
        mIvLoading.startAnimation(rotateAnimation);

(4) TranslateAnimation(平移)

  1. XML 实现方式:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="100"
    android:toYDelta="100" />
  • fromXDelta, fromYDelta : 起始时 XY 座标;
  • toXDeltatoYDelta : 动画结束时 X, Y 的座标;

获取动画并设置给对应的 View

Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_translate);
        mIvLoading.startAnimation(translateAnimation);
  1. 代码实现方式:
Animation translateAnimation = new TranslateAnimation(0, 0, 100, 100);
        translateAnimation.setDuration(1000);
        mIvLoading.startAnimation(translateAnimation);

(5) AnimationSet(动画集合)

XML 实现方式:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <!-- 各种单独特效的杂糅 -->
    <alpha
        android:duration="1000"
        android:fromAlpha="1.0"
        android:toAlpha="0.1" />

    <rotate
        android:duration="1000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="720" />

    <scale
        android:duration="1000"
        android:fromXScale="0.1"
        android:fromYScale="0.1"
        android:toXScale="1.0"
        android:toYScale="1.0" />

    <translate
        android:duration="1000"
        android:fillAfter="true"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100"
        android:toYDelta="100" />
</set>

获取动画并设置给对应的 View

Animation animationSet = AnimationUtils.loadAnimation(this, R.anim.tween_anim_set);
        mIvLoading.startAnimation(animationSet);

代码方式实现:

AnimationSet animationSet = new AnimationSet(true);
        Animation alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_alpha);
        Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_scale);
        Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_rotate);
        Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_anim_translate);
        animationSet.addAnimation(alphaAnimation);
        animationSet.addAnimation(scaleAnimation);
        animationSet.addAnimation(rotateAnimation);
        animationSet.addAnimation(translateAnimation);

        mIvLoading.startAnimation(animationSet);

四、动画监听器

有时,我们需要知道动画的一些状态,然后在不同的周期做相应的操作,这时可以使用动画监听器,如下:

animationSet.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        //动画开始时调用
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        //动画结束时调用
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
        //动画重复时调用
    }
    });
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容