这一篇,学会Android全部动画

本文详细介绍了Android的三种动画类型:帧动画、补间动画和属性动画。帧动画适用于复杂的个性化动画效果,补间动画用于视图的标准动画效果,如平移、旋转、缩放和透明度。属性动画则作用于任意对象,能实现更自定义的动画效果。文章还提供了具体的实现代码和示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android三种动画

三方:https://blog.youkuaiyun.com/zuo_er_lyf/article/details/79716840

Android动画分三类:帧动画(frame animation),补间动画(tween animation),属性动画(property animation)

一、帧动画(frame animation)

1、作用对象:视图控件(view)

1.如Android的TextView、Button等等
2.不可作用于View组件的属性,如:颜色、背景、长度等等

2、原理

  • 将动画拆分成帧的形式,每一帧对应一张图片
  • 本质就是:按顺序播放一组预先定义好的图片

3、具体使用

步骤①:将序列图片放到drawable中
步骤②:设置启动动画:Java和xml
方式一:XML实现

  • step1 在res/drawable中创建动画效果.XML文件
  • step2 设置动画资源
    music_anim.xml
<?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/sound_00030"
        android:duration="100" />
    <item
        android:drawable="@drawable/sound_00031"
        android:duration="100" />

</animation-list>
  • step3 在Java代码中 载入&启动
public class MainActivity extends AppCompatActivity {

    private AnimationDrawable animationDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageView imageview = (ImageView) findViewById(R.id.imageview);
        Button btn_start = (Button) findViewById(R.id.btn_start);
        Button btn_stop = (Button) findViewById(R.id.btn_stop);

        //开启动画
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //设置动画
                imageview.setImageResource(R.drawable.music_anim);
                //获取动画对象
                animationDrawable = (AnimationDrawable) imageview.getDrawable();
                //开启动画
                animationDrawable.start();
            }
        });

        //停止动画
        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animationDrawable.stop();
            }
        });
    }
}

方式2:在Java代码中实现

 animationDrawable = new AnimationDrawable();
        for (int i = 30; i <= 59; i++) {
            int id = getResources().getIdentifier("sound" + i, "drawable", getPackageName());
            Drawable drawable = getResources().getDrawable(id);
            animationDrawable.addFrame(drawable, 1);
        }
        // <--开始动画-- >
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animationDrawable.setOneShot(false);
                imageview.setImageDrawable(animationDrawable);
                // 获取资源对象
                animationDrawable.stop(); // 特别注意:在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次
                animationDrawable.start(); // 启动动画 } });
            }
        });
        // <-- 停止动画 -->
        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.stop();
            }
        });

4、特点

  • 优点:使用简单、方便
  • 缺点: 容易引起 OOM,因为会使用大量 & 尺寸较大的图片资源

使用时一定注意避免使用大图片,否则会引起OOM

5、应用场景

  • 较为复杂的个性化动画效果。

二、补间动画

1、作用对象

  • 视图 (view)

1.如Android的TextView、Button等等
2.不可作用于View组件的属性,如:颜色、背景、长度等等

2、原理

  • 通过确定开始视图样式&结束视图样式、中间动画变化过程由系统补全来确定一个动画

动效样式有:translation、alpha、scale、rotate

涉及到四个类:TranslateAnimation、AlphaAnimation、RotateAnimation、ScaleAnimation

3、具体使用

  • 补间动画使用方式分两种:Java代码&xml中实现

前者优点:动画描述的可读性更好
后者优点:动画效果可动态创建

3.1 平移动画(translate)
方式一:xml中实现

  • step1:在res/anim中创建动效.xml文件
  • step2:设置平移动画的参数
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:startOffset="1000"
    android:fillAfter="false"
    android:fillBefore="true"
    android:fillEnabled="true"
    android:repeatCount="0"
    android:repeatMode="restart"

    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="500"
    android:toYDelta="500" />
  • step3 在Java代码中创建animation对象&播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
btn_start.startAnimation(animation);

方式二:Java代码中实现

TranslateAnimation translateAnimation = new TranslateAnimation(0, 500, 0, 500);
translateAnimation.setDuration(5000);
translateAnimation.setRepeatMode(Animation.REVERSE);
translateAnimation.setRepeatCount(3);
btn_start.startAnimation(translateAnimation);

3.2 缩放动画(scale)
方式一:xml中实现

  • step1:在res/anim中创建动效.xml文件(scale_animation.xml)
  • step2:设置缩放动画的参数
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:startOffset="1000"
    android:fillAfter="false"
    android:fillBefore="true"
    android:fillEnabled="true"
    android:repeatCount="5"
    android:repeatMode="reverse"

    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:toXScale="2"
    android:toYScale="2"
    android:pivotX="50%"
    android:pivotY="50%"/>
  • step3 在Java代码中创建animation对象&播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale_animation);
btn_start.startAnimation(animation);

方式二:Java代码中实现

ScaleAnimation scaleAnimation = new ScaleAnimation(0, 2, 0, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(5000);
        btn_start.startAnimation(scaleAnimation);

3.3 旋转动画(rotate)
方式一:xml中实现

  • step1:在res/anim中创建动效.xml文件(rotate_animation.xml)
  • step2:设置旋转动画的参数
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:startOffset="0"
    android:fillAfter="true"
    android:fillBefore="false"
    android:repeatCount="5"
    android:repeatMode="reverse"

    android:fromDegrees="30"
    android:toDegrees="150"
    android:pivotY="50%"
    android:pivotX="0"/>
  • step3 在Java代码中创建animation对象&播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation);
        btn_start.startAnimation(animation);

方式二:Java代码中实现

RotateAnimation rotateAnimation = new RotateAnimation(30, 150, 0.5f, 0.5f);
rotateAnimation.setRepeatCount(5);
rotateAnimation.setDuration(5000);
rotateAnimation.setRepeatMode(Animation.REVERSE);
btn_start.startAnimation(rotateAnimation);

3.4 透明度动画(alpha)
方式一:xml中实现

  • step1:在res/anim中创建动效.xml文件
  • step2:设置透明度动画的参数
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="false"
    android:fillBefore="true"
    android:fillEnabled="true"
    android:fromAlpha="0.5"
    android:repeatCount="5"
    android:repeatMode="reverse"

    android:startOffset="1000"
    android:toAlpha="3" />
  • step3 在Java代码中创建animation对象&播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
btn_start.startAnimation(animation);

方式二:Java代码中实现

AlphaAnimation alphaAnimation = new AlphaAnimation(0.5f, 3.0f);
        alphaAnimation.setDuration(5000);
        btn_start.startAnimation(alphaAnimation);

5、组合动画set

  • 上面讲的都是单个动画效果;而实际中很多需求都需要同时使用平移、缩放、旋转 & 透明度4种动画,即组合动画
  • 使用组合动画需要用到标签

方式一:xml中实现

  • step1:在res/anim中创建动效.xml文件
  • step2:设置组合动画的参数
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="3000"
    android:fillAfter="false"
    android:fillBefore="true"
    android:fillEnabled="true"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:startOffset="1000">
    <rotate
        android:duration="1000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite"
        android:repeatMode="restart"
        android:toDegrees="360" />
    // 设置平移动画,语法同单个动画
    <translate
        android:duration="10000"
        android:fromXDelta="-50%p"
        android:fromYDelta="0"
        android:startOffset="1000"
        android:toXDelta="50%p"
        android:toYDelta="0" />
    // 设置透明度动画,语法同单个动画
    <alpha
        android:duration="3000"
        android:fromAlpha="1.0"
        android:startOffset="7000"
        android:toAlpha="0.0" />
    // 设置缩放动画,语法同单个动画
    <scale
        android:duration="1000"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="4000"
        android:toXScale="0.5"
        android:toYScale="0.5" />
</set>

组合动画独特的属性 android:shareinterpolator = “true”
如果集合不指定插值器,那么子动画需要单独设置
组合动画播放时是全部动画同时开始
如果想不同动画不同时间开始就要使用android:startOffset属性来延迟单个动画播放时间

  • step3 在Java代码中创建animation对象&播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_animation);
btn_start.startAnimation(animation);

方式二:Java代码中实现

//集合动画对象创建
        AnimationSet animationSet = new AnimationSet(true);

        animationSet.setRepeatMode(Animation.REVERSE);
        animationSet.setRepeatCount(1);

        //旋转动画对象创建
        Animation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(1000);
        rotate.setRepeatMode(Animation.RESTART);
        rotate.setRepeatCount(Animation.INFINITE);


        //透明度动画对象创建
        Animation alpha = new AlphaAnimation(1, 0);
        alpha.setDuration(3000);
        alpha.setStartOffset(7000);


        //平移动画对象创建
        Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT, -0.5f, TranslateAnimation.RELATIVE_TO_PARENT, 0.5f, TranslateAnimation.RELATIVE_TO_SELF, 0, TranslateAnimation.RELATIVE_TO_SELF, 0);
        translate.setDuration(10000);

        //缩放动画对象创建
        Animation scale1 = new ScaleAnimation(1, 0.5f, 1, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scale1.setDuration(1000);
        scale1.setStartOffset(4000);


        //将创建每一种子动画添加到组合动画
        animationSet.addAnimation(alpha);
        animationSet.addAnimation(rotate);
        animationSet.addAnimation(translate);
        animationSet.addAnimation(scale1);

        //开启动画
        btn_start.setAnimation(animationSet);

6、动画监听

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

7、应用场景

  • 7.1 标准的动画效果
    补间动画常用于视图View的一些标准动画效果:平移、旋转、缩放 & 透明度;
  • 7.2 特殊的应用场景
    Activity 的切换效果
    Fragement 的切换效果
    视图组(ViewGroup)中子元素的出场效果

三、属性动画(Property Animation)
1、简介:属性动画是在Android3.0(API11)提出的全新的动画
2、出现原因:解决帧动画与补间动画的不足

  • ①作用对象单一:只能作用于view
  • ②没有改变view的属性,只是改变视觉效果
  • ③动画效果单一

3、定义:作用于任意对象,实现各种自定义动画效果
4、工作原理:在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果
有两个很重要的类ValueAnimator 类 & ObjectAnimator

5、具体使用

5.1 ValueAnimator类
定义: 属性动画中最核心的一个类
原理: 通过不断控制 值 的变化,再不断 手动 赋给对象的属性,从而实现动画效果
ValueAnimator中有三个重要的方法实现动画:

  • ValueAnimator.ofInt(int… values)
  • ValueAnimator.ofFloat(float… values)
  • ValueAnimator.ofObject(int… values)
5.1.1 ValueAnimator.ofInt(int… values)
  • 作用:将初始值以整型的形式过度到结束值

    估值器默认是整形估值器IntEvaluator

  • 具体使用

//属性动画
//step1 设置属性动画的初始值与结束值
ValueAnimator valueAnimator = ValueAnimator.ofInt(btn_property_animation.getLayoutParams().width, 1000);
// ofInt()作用有两个 
// 1. 创建动画实例 
// 2. 将传入的多个Int参数进行平滑过渡:此处传入0和1,表示将值从0平滑过渡到1 // 如果传入了3个Int参数 a,b,c ,则是先从a平滑过渡到b,再从b平滑过渡到C,以此类推 
// ValueAnimator.ofInt()内置了整型估值器,直接采用默认的.不需要设置,即默认设置了如何从初始值 过渡到 结束值 

//step2  设置动画的各种属性
//设置动画运行时长
valueAnimator.setDuration(5000);
//设置动画启动延时时长
valueAnimator.setStartDelay(500);
//设置动画重复次数=次数+1
//动画次数=infinite  动画无限重复
valueAnimator.setRepeatCount(6);
 // 设置重复播放动画模式
// ValueAnimator.RESTART(默认):正序重放
// ValueAnimator.REVERSE:倒序回放
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);

//step3 将改变的值手动赋给对象的属性:通过动画的更新监听器
//值每改变一次,方法就回被调用一次
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     @Override
     public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //获得变化后的属性
                int curValue = (int) valueAnimator.getAnimatedValue();
                //值每次更改后手动赋给按钮
                btn_property_animation.getLayoutParams().width = curValue;
                //刷新视图,重新绘制
                btn_property_animation.requestLayout();
            }
        });

        valueAnimator.start();
5.1.2 ValueAnimator.ofFloat(float… values)
  • 作用:将初始值以浮点型的形式过度到结束值

    估值器默认是浮点型估值器FloatEvaluator

  • 具体使用:与ofInt一样

5.1.3 ValueAnimator.ofObject(int… values)
  • 作用:将初始值以对象的形式过度到结束值

    通过操作对象实现动画

  • 具体使用

// 创建初始动画时的对象 & 结束动画时的对象
myObject object1 = new myObject(); 
ValueAnimator anim = ValueAnimator.ofObject(new myObjectEvaluator(), object1, object2); 
// 创建动画对象 & 设置参数
// 参数说明
// 参数1:自定义的估值器对象(TypeEvaluator 类型参数)
// 参数2:初始动画的对象 
// 参数3:结束动画的对象 
anim.setDuration(5000);
anim.start();
  • 实例演示

  • ~~~~~step1:定义对象类

    因为ValueAnimator.ofObject()是面向对象操作的,所以需要自定义对象类

public class MyPoint {

    private float x;
    private float y;

    public MyPoint(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }
}
  • ~~~~~step2:根据需求实现估值器借口TypeEvaluator
public class PiontEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        //将初始值和结束值抢转成point类型
        MyPoint startPoint = (MyPoint) startValue;
        MyPoint endPoint = (MyPoint) endValue;

        //根据fraction计算当前动画的x和y值
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());

        //将计算后的坐标封装到一个新的point对象中,然后返回
        MyPoint point = new MyPoint(x, y);

        return point;
    }
}
  • ~~~~~step3:将属性动画作用到自定义的view上
public class MyView extends View {

    //需要用到的变量
    private static final float RADIUS = 70f;
    private MyPoint curPoint;
    private Paint mPaint;

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.GREEN);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //如果当前坐标为空(第一次)
        if (curPoint == null) {
            //创建一个点对象
            MyPoint point = new MyPoint(RADIUS, RADIUS);

            //在该点画一个圆:圆心(80,80),半径80
            float x = point.getX();
            float y = point.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);

            //将属性动画作用到view中
            MyPoint startPoint = new MyPoint(RADIUS, RADIUS);
            MyPoint endPoint = new MyPoint(700, 1000);

            //创建动画对象,设置初始值和结束值
            ValueAnimator valueAnimator = ValueAnimator.ofObject(new PiontEvaluator(), startPoint, endPoint);
            valueAnimator.setDuration(5000);

            //给动画添加更新 监听器
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    curPoint = (MyPoint) valueAnimator.getAnimatedValue();
                    invalidate();
                }
            });

            valueAnimator.start();
        } else {
            //当前坐标为空
            float y = curPoint.getY();
            float x = curPoint.getX();

            canvas.drawCircle(x, y, RADIUS, mPaint);
        }
    }
}
  • ~~~~~step4:在布局中加入自定义view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="40dp"
    tools:context="com.yunjiai.admin.animation.MainActivity">

   <com.yunjiai.admin.animation.MyView
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</RelativeLayout>

5.2 ObjectAnimator类
5.2.1原理: 通过不断控制 值 的变化,再不断 自动 赋给对象的属性,从而实现动画效果

如直接改变 View的 alpha 属性 从而实现透明度的动画效果
继承自ValueAnimator类,即底层的动画实现机制是基于ValueAnimator类

ObjectAnimator与 ValueAnimator类的区别:

  • ValueAnimator 类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作;
  • ObjectAnimator 类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;

5.2.2 具体使用

ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values); 
// ofFloat()作用有两个 
// 1. 创建动画实例 
// 2. 参数设置:参数说明如下 
// Object object:需要操作的对象 
// String property:需要操作的对象的属性 
// float ....values:动画初始值 & 结束值(不固定长度) 
// 若是两个参数a,b,则动画效果则是从属性的a值到b值 
// 若是三个参数a,b,c,则则动画效果则是从属性的a值到b值再到c值 
// 以此类推 
// 至于如何从初始值 过渡到 结束值,同样是由估值器决定,此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解 
anim.setDuration(500); // 设置动画运行的时长 
anim.setStartDelay(500); // 设置动画延迟播放时间 
anim.setRepeatCount(0); // 设置动画重复播放次数 = 重放次数+1 // 动画播放次数 = infinite时,动画无限重复 
anim.setRepeatMode(ValueAnimator.RESTART); // 设置重复播放动画模式 
// ValueAnimator.RESTART(默认):正序重放 // ValueAnimator.REVERSE:倒序回放 
animator.start(); // 启动动画 

5.2.3 使用实例

  • 平移
  //获得当前按钮的位置
        float curX = btn_property_animation.getTranslationX();

        ObjectAnimator alpha = ObjectAnimator.ofFloat(btn_property_animation, "translationX",curX, 360,720);
        alpha.setDuration(5000);
        alpha.setRepeatCount(10);
        alpha.setRepeatMode(ValueAnimator.REVERSE);
        alpha.start();
  • 旋转
  ObjectAnimator alpha = ObjectAnimator.ofFloat(btn_property_animation, "rotation",0, 360,720);
        alpha.setDuration(5000);
        alpha.setRepeatCount(10);
        alpha.setRepeatMode(ValueAnimator.REVERSE);
        alpha.start();
  • 透明度
ObjectAnimator alpha = ObjectAnimator.ofFloat(btn_property_animation, "alpha",0f, 1f);
        alpha.setDuration(5000);
        alpha.setRepeatCount(10);
        alpha.setRepeatMode(ValueAnimator.REVERSE);
        alpha.start();
  • 缩放
ObjectAnimator alpha = ObjectAnimator.ofFloat(btn_property_animation, "scaleY",1f, 2f,3f,5f,1f,0.2f);
        alpha.setDuration(5000);
        alpha.setRepeatCount(10);
        alpha.setRepeatMode(ValueAnimator.REVERSE);
        alpha.start();

从上边的例子可以看出只要改变ObjectAnimator.ofFLoat()中的第二个参数就可以实现各种动画,下边是补充属性:

属性作用数值类型
Alpha控制View的透明度float
TranslationX控制X方向的位移float
TranslationY控制Y方向的位移float
ScaleX控制X方向的缩放倍数float
ScaleY控制Y方向的缩放倍数float
Rotation控制以屏幕方向为轴的旋转度数float
RotationX控制以X轴为轴的旋转度数float
RotationY控制以Y轴为轴的旋转度数float
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值