【Android】三大动画的实践

一、引言

动画是 Android 开发中非常重要的一部分,它不仅能提升界面效果,还能改善用户的操作体验。在开发中,动画的选择和使用可能会直接影响应用的流畅度和用户满意度。因此,了解 Android 提供的三种动画框架,并掌握它们的用法,是我们迈向开发进阶的重要一步。

二、入门实践

2.1帧动画

2.1.1帧动画介绍

Q: 什么是帧动画?

帧动画(Frame Animation)本质上是一种基于时间的逐帧动画技术。通过定义一组按顺序播放的图片(称为动画帧),并为每帧设定展示时间,使动画看起来流畅。

Q: 帧动画的工作原理是什么?

帧动画的核心是图片切换:准备一系列图片(帧),每帧代表动画中的某一状态;按设定的时间间隔依次切换这些图片,模拟出动态效果。动画完成后可以选择是否重复播放。

Q: 帧动画一般用于哪里?有什么优缺点?

帧动画适用于以下场景:

  • UI 动效:例如加载指示器、按钮点击时的装饰性特效。
  • 装饰性动画:用于角色行走、跳跃等简单动画。
  • 短时特效:比如爆炸效果、烟雾特效。

优点:实现简单,适合展示已有的图片资源。不需要复杂的数学或物理知识,快速实现效果。

缺点:每一帧是单独的图片,占用大量内存,容易导致内存溢出。无法根据实时交互动态生成效果,缺乏灵活性。

2.1.1帧动画介绍

具体实现步骤

(1)准备图片资源

帧动画的核心是图片资源,需要一组连续的图片来构成动画帧。这些图片应存在 res/drawable 目录下,并且要保证图片尺寸和格式一致,以保证动画的流畅性。

(2)创建帧动画 XML 文件

res/drawable 目录下新建帧动画的 XML 文件,命名为 frame.xml。这个文件用来定义每一帧图片以及其展示时长。其中++android:drawable:++ 指定每一帧使用的图片资源。++android:duration:++每帧图片展示的时间,单位为毫秒,大家可以根据自己需求进行修改。示例如下:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/p2" android:duration="120"/>
    <item android:drawable="@drawable/p3" android:duration="120"/>
    <item android:drawable="@drawable/p4" android:duration="120"/>
    <item android:drawable="@drawable/p5" android:duration="120"/>
    <item android:drawable="@drawable/p6" android:duration="120"/>
</animation-list>

(3)布局文件定义

在布局文件中,将帧动画文件作为背景应用到一个视图组件。这里使用 RelativeLayout 容器。其中++android:background:++ 设置帧动画文件 frame.xml 作为视图的背景。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/frame"
    />

(4)编写逻辑代码

在 MainActivity.java 中,通过 AnimationDrawable 类控制帧动画的启动和停止。其中AnimationDrawable: 用于操作帧动画的类,通过 start() 方法启动动画,**stop()**方法停止动画。点击事件: 用户点击布局时,切换动画的启动和停止状态。完整代码如下:

java 复制代码
package com.example.animation;

import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import androidx.appcompat.app.AppCompatActivity;

import com.example.animation.R;

public class MainActivity extends AppCompatActivity {
    private boolean isPlaying = false; // 控制动画的播放状态

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

        // 获取 RelativeLayout 容器
        RelativeLayout relativeLayout = findViewById(R.id.rl);

        // 将背景强制转换为 AnimationDrawable
        AnimationDrawable animDrawable = (AnimationDrawable) relativeLayout.getBackground();

        // 设置点击事件,切换动画播放状态
        relativeLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!isPlaying) {
                    animDrawable.start(); // 启动动画
                    isPlaying = true;
                } else {
                    animDrawable.stop(); // 停止动画
                    isPlaying = false;
                }
            }
        });
    }
}

(5)运行演示

启动项目,点击图片,就可以看到我们所创建的帧动画了。

2.2视图动画

2.2.1视图动画介绍

Q: 视图动画是什么?

视图动画(View Animation)是一种对视图(View)进行的视觉效果变化,不会改变视图本身的布局或属性。通过视图动画,可以实现对视图的平移、旋转、缩放、透明度等效果,但这些变化仅在视觉上生效,不会修改视图的实际属性(例如坐标、大小等)。

Q: 视图动画有哪些常见应用场景?

视图动画通常用于简单的界面交互和动效设计,例如:

  • 按钮点击效果:当用户点击按钮时,按钮可以实现缩放、旋转或透明度变化等效果。
  • 页面切换动画:页面元素之间的滑动、淡入淡出等过渡动画。
  • 用户反馈动画:如加载、成功、失败等状态反馈,常用透明度或旋转动画。

Q: 视图动画的实现方式是什么?

在 Android 中,视图动画通过 Animation 类实现。你可以通过 XML 或代码定义动画。XML 定义的动画文件更为简洁、可重用,而代码实现则提供了更多的灵活性。

常见的视图动画包括:

  1. Alpha动画:控制视图的透明度变化。
  2. Rotate动画:控制视图的旋转角度。
  3. Scale动画:控制视图的缩放效果。
  4. Translate动画:控制视图的位置移动。

2.2.2视图动画具体实现

现在,我们来一步一步实现一个简单的视图动画,给 ImageView 添加几个动画效果,包括透明度变化(alpha)、旋转(rotate)、缩放(scale)和位移(translate)。

(1)创建布局文件

首先,在 activity_main.xml 中,定义一个 ImageView,用于显示我们要应用动画的图片:

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:adjustViewBounds="true"
        android:maxWidth="300dp"
        android:maxHeight="300dp"
        android:src="@drawable/ceshi" />
 
</RelativeLayout>

(2)创建动画文件并实现动画操作

1.透明度动画(Alpha Animation) 透明度动画会使视图从透明(alpha=0)渐变到不透明(alpha=1),或者反向过渡。

res/anim/ 目录下创建一个 XML 文件,命名为 alpha.xml,并写入以下内容:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="2000"/>
</set>

其中,++fromAlpha="0"指++ 起始透明度:0 = 完全透明,++toAlpha="1"++指结束透明度:1 = 完全不透明

MainActivity.java 中,我们加载并启动透明度动画。启动动画代码相同,只需要更换xml文件名称即可,后面就不再赘述了。

java 复制代码
package com.example.donghua2;
 
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
 
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = findViewById(R.id.iv);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha);
                
                imageView.startAnimation(animation);
            }
        });
    }
}

启动项目后点击图片效果如下,可以发现图片在我们设置的两秒钟成功实现了由透明(alpha=0)渐变到不透明(alpha=1)的转变。

**2.旋转动画(Rotate Animation)**旋转动画让视图围绕某个点(通常是视图的中心)进行旋转。你可以设置旋转的起始角度和终止角度,以及旋转的持续时间。

res/anim/ 目录下创建一个 XML 文件,命名为 rotate.xml,并写入以下内容:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="2000"/>
</set>

其中pivotX="50%" / pivotY="50%":旋转中心点,控件正中心

MainActivity.java 中加载并启动旋转动画:

java 复制代码
Animation animation1 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotate);
imageView.startAnimation(animation1);

启动项目后我们可以发现初始状态:图片呈水平位置,点击图片后,图片进行绕着中心旋转一圈最后回到原来的水平位置。

**3. 缩放动画(Scale Animation)**缩放动画可以让视图在水平方向和垂直方向上进行缩放。你可以控制视图的初始和终止缩放比例。

res/anim/ 目录下创建一个 XML 文件,命名为 scale.xml,并写入以下内容:

XML 复制代码
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:fromXScale="1"
        android:fromYScale="1"
        android:toXScale="0.5"
        android:toYScale="0.5"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="2000"/>
</set>

MainActivity.java 中加载并启动缩放动画:

java 复制代码
Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scale);
imageView.startAnimation(animation2);

启动项目后可以观察到图片由原始大小缩小到了原始大小的50%。

**4. 位移动画(Translate Animation)**位移动画使视图从一个位置移动到另一个位置。你可以设置水平和垂直方向上的偏移量。

res/anim/ 目录下创建一个 XML 文件,命名为 translate.xml,并写入以下内容:

XML 复制代码
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="-350"
        android:fromYDelta="-350"
        android:toXDelta="350"
        android:toYDelta="350"
        android:duration="2000"/>
</set>

MainActivity.java 中加载并启动位移动画:

java 复制代码
Animation animation3 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate);
imageView.startAnimation(animation3);

运行项目后可以发现图片由左上角移动到了右下角的位置。

2.3属性动画

2.3.1属性动画介绍

Q: 什么是属性动画?

属性动画是 Android 动画框架中最强大的一种。它不仅能对视图的外观进行动画处理,还可以动态地改变对象的任意属性。属性动画通过 ObjectAnimator 或 ValueAnimator 来实现,对视图的具体属性进行动态变化,比如改变颜色、透明度、位置等。

Q: 属性动画和其他动画框架有什么区别?

与帧动画和视图动画不同,属性动画可以作用于任何对象的任何属性,甚至是非视图对象(如普通的 Java 对象)。属性动画提供了更多的灵活性,适用于复杂的动画需求,比如动态变化的位置、大小、透明度等。

Q: 常见的属性动画有哪几种?

ObjectAnimator:用于动画化视图的某个特定属性(例如位置、透明度、旋转、缩放等)。

ValueAnimator :用于执行数值的动画变化,适用于非视图对象或需要对数值进行更精细控制的情况。

2.3.2属性动画具体实现

在这部分,我们将通过一个简单的代码示例,来演示如何在 Android 中使用属性动画,具体包括 ObjectAnimator 和 ValueAnimator 的使用。

1. 使用 ValueAnimator:

ValueAnimator 是一种更基础的属性动画,它仅仅负责计算动画的数值变化,不直接作用于视图。我们通常可以通过 addUpdateListener 来监听动画的数值变化,并应用到界面的某个元素上。

java 复制代码
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = findViewById(R.id.iv);

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
        valueAnimator.setDuration(2000);

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                Log.d("leo", "onAnimationUpdate: " + value);
                // 用动画值控制透明度
                imageView.setAlpha(value);
            }
        });
        valueAnimator.start();
    }
}

假设我们在监听动画中透明度的值,启动项目在界面中透明度变化的同时,它的值从 0 变到 1,持续时间为 2 秒。每次动画更新时,会触发 onAnimationUpdate() 方法,并打印出当前的动画值。在日志输出内容中我们可以看到对应的输出内容。

2.使用 ObjectAnimator:

ObjectAnimator 是对视图属性的直接操作,它能直接对某个视图的属性进行动画化,比如透明度、位置、缩放等。下面代码创建了一个 ObjectAnimator 动画,指定目标视图为 TextView,动画的属性为 "alpha"(透明度)。这个动画的效果是让 TextView 从完全透明变为完全不透明,动画持续时间为 4 秒。

java 复制代码
TextView textView = findViewById(R.id.tv);  // 获取到目标视图
 
// 创建一个 ObjectAnimator,设置视图的透明度属性从 0 到 1
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView, "alpha", 0f, 1f);
objectAnimator.setDuration(4000);  // 设置动画持续时间为 4 秒
objectAnimator.start();  // 启动动画

启动项目后展示如下,其实与视图动画中的透明度变化很类似,但是在属性动画中可以进行更复杂的属性配置。

3. 为动画添加监听器:

ObjectAnimator 和 ValueAnimator 都可以通过 AnimatorListener 或 AnimatorUpdateListener 来添加监听器,处理动画的不同阶段。通过 addListener() 方法,我们可以监听动画的开始、结束、取消和重复事件。例如,当动画开始时,我们可以在日志中打印"动画开始"。

java 复制代码
objectAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(@NonNull Animator animator) {
        Log.e("Animation", "动画开始");
    }
 
    @Override
    public void onAnimationEnd(@NonNull Animator animator) {
        Log.e("Animation", "动画结束");
    }
 
    @Override
    public void onAnimationCancel(@NonNull Animator animator) {
        Log.e("Animation", "动画取消");
    }
 
    @Override
    public void onAnimationRepeat(@NonNull Animator animator) {
        Log.e("Animation", "动画重复");
    }
});

三、动画对比与场景选择

特性 视图动画(View Animation) 帧动画(Frame Animation) 属性动画(Property Animation)
操作对象 仅限于 View 类的基本属性 通过图片帧实现动画 任意对象及其任意属性
动画类型 位移、缩放、旋转、透明度等 静态图片按顺序切换 任意属性(如颜色、透明度、路径等)
性能消耗 较低(仅限 View 属性的更新) 较高(需要加载和绘制多张图片) 较高(涉及多个属性和复杂计算)
适用场景 简单的 UI 动画、过渡效果 静态图像动画、图标动画 自定义复杂动画、路径动画、视图属性变化
灵活性 较低,无法对属性进行复杂控制 较低,仅限于图像切换 高,支持多种属性及动画形式
实现复杂度 简单,易于实现 简单,但内存占用大 复杂,需要配置对象和属性

选择建议

**视图动画:**如果需求是简单的界面动画,如按钮点击时的缩放、透明度变化,或者页面切换时的过渡动画,使用视图动画即可。

**帧动画:**适用于基于图像序列的动画,常见于图标动画、加载动画等,特别适合需要呈现多个静态图像的场景。

**属性动画:**当需要对对象的多个属性进行精细控制时,或者需要动态改变视图或对象的任意属性(如颜色、透明度、路径等),应选择属性动画。它支持更灵活和复杂的动画效果,适用于高级交互和自定义动画效果。

相关推荐
Mars-xq1 小时前
VSCode 开发 Android 时,类、方法无法跳转
android·ide·vscode
2601_961766642 小时前
【分享】Resprite安卓版|专业像素绘画,游戏美术创作工具
android·游戏美术
Mars-xq2 小时前
VSCode 开发Android 新手必装插件清单
android·ide·vscode
Wonderful U2 小时前
Python+Django实战|社区物业管理系统:业主档案、车位管理、物业费收缴、线上报修、投诉建议、园区公告、日常巡检
android·python·django
三少爷的鞋3 小时前
现代 Android 官方为什么更推荐 Repository 暴露 `suspend fun`,而不是在内部 `launch`
android
黄林晴14 小时前
Google Play 发版链路全面重构:合规前置、审核自动化、生态全面收紧
android·google
通玄16 小时前
Jetpack Compose 入门系列(四):动画基本使用
android
杉氧16 小时前
Kotlin 协程深度解析②:生存指南——掌握结构化并发的生命线
android·kotlin
故渊at16 小时前
第四板块:Android 输入系统与触控事件 | 第十五篇:InputReader 与 InputDispatcher 的触控流水线
android·anr·输入系统·inputdispatcher·inputreader·触控事件·inputevent