楼主: 2h29fN8Ypl1w
59 0

[互联网] Android的动画详解 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-7-23
最后登录
2018-7-23

楼主
2h29fN8Ypl1w 发表于 2025-11-14 12:42:04 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

在安卓开发中,动画是提升用户体验的关键元素之一。下面我将为你概述安卓的几种主要动画形式、它们的优势与不足、典型的应用场景,并解决你有关点击事件和属性约束的具体疑问。

三种核心动画类型

动画类型 核心机制 优点 缺点 典型使用场景
补间动画 设置起始和终止状态,系统计算中间帧。 实现简便,无需逐帧定义,动画效果流畅。 仅改变视图绘制的位置,不改变视图的真实属性(例如位置、尺寸),导致点击事件仍发生在初始位置。 视图的渐隐渐现、平移、旋转、缩放等效果。
属性动画 通过持续修改目标对象的属性值来创建动画。 实际改变视图属性,交互逻辑准确;可以对任意对象的属性进行动画化。 API 11及以上版本原生支持,兼容旧版需额外处理。 复杂的交互动画,如背景色变换、自定义属性的动画。
帧动画 顺序播放一系列静态图片。 制作容易,控制精确。 可能占用大量内存;动画效果不够灵活。 如加载中的动画、复杂特效。

三种动画的使用示例

帧动画

帧动画类似于翻页书籍,通过快速切换图像实现动画效果。

  • 定义XML动画文件 在
    res/drawable/
    目录下创建XML文件,例如
    anim_frame.xml
    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false"> <!-- false表示循环播放 -->
        <item
            android:drawable="@drawable/frame1"
            android:duration="100" />
        <item
            android:drawable="@drawable/frame2"
            android:duration="100" />
        <!-- ... 更多帧 -->
    </animation-list>
  • 在代码中启动动画
    ImageView imageView = findViewById(R.id.imageView);
    imageView.setBackgroundResource(R.drawable.anim_frame);
    AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getBackground();
    
    // 注意:不建议在onCreate()中直接调用start(),因为窗口未完全初始化
    // 推荐在onWindowFocusChanged()或用户交互后启动
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            animationDrawable.start();
        }
    }

关键点:为了避免动画不播放,启动时机很重要,最好是在

onWindowFocusChanged
或用户交互后开始。

补间动画

补间动画通过定义起始和终止状态,由系统自动生成中间帧的动画。它提供了四种基本变换。

  1. 定义动画XML文件 在
    res/anim/
    目录下创建文件,例如
    anim_set.xml
    ,可以组合多种效果:
    <!-- 淡入同时缩放的组合动画 -->
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:shareInterpolator="false"
        android:fillAfter="true"> <!-- 动画结束后保持状态 -->
    
        <alpha
            android:fromAlpha="0.0"
            android:toAlpha="1.0"
            android:duration="1000" />
    
        <scale
            android:fromXScale="0.5"
            android:toXScale="1.0"
            android:fromYScale="0.5"
            android:toYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:duration="1000" />
    </set>
  2. 在代码中应用动画
    ImageView imageView = findViewById(R.id.imageView);
    // 加载XML动画
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_set);
    imageView.startAnimation(animation);
    
    // 或者,也可以完全用代码创建动画
    AnimationSet set = new AnimationSet(true);
    AlphaAnimation alphaAnim = new AlphaAnimation(0.0f, 1.0f);
    alphaAnim.setDuration(1000);
    set.addAnimation(alphaAnim);
    
    ScaleAnimation scaleAnim = new ScaleAnimation(0.5f, 1.0f, 0.5f, 1.0f, 
                                                 Animation.RELATIVE_TO_SELF, 0.5f, 
                                                 Animation.RELATIVE_TO_SELF, 0.5f);
    scaleAnim.setDuration(1000);
    set.addAnimation(scaleAnim);
    
    imageView.startAnimation(set);

核心局限:补间动画只是视觉上的变化,视图的实际位置和尺寸等属性并未改变。例如,你将一个按钮从顶部平移到底部,点击按钮底部不会响应,但点击其原始位置却会。

属性动画

属性动画通过动态地修改对象的属性值来实现动画,是功能最强大的动画系统。

  1. 值动画:手动管理数值变化
    // 创建一个在0到100之间变化的数值动画
    ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
    valueAnimator.setDuration(1000);
    
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int currentValue = (int) animation.getAnimatedValue();
            // 手动将当前值应用到目标对象,例如更新View的布局参数
            ViewGroup.LayoutParams params = someView.getLayoutParams();
            params.height = currentValue;
            someView.setLayoutParams(params);
        }
    });
    valueAnimator.start();
  2. 对象动画:自动更新属性
    // 自动改变View的透明度(系统会自动寻找并调用setAlpha方法)
    ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
    alphaAnimator.setDuration(1000);
    alphaAnimator.start();
    
    // 平移动画(实际改变的是translationX属性)
    ObjectAnimator translateAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 200f);
    translateAnimator.setDuration(1000);
    translateAnimator.start();
  3. 组合动画:协调多个动画 使用
    AnimatorSet
    可以精确控制多个动画的播放顺序:
    ObjectAnimator animX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.5f);
    ObjectAnimator animY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.5f);
    
    AnimatorSet set = new AnimatorSet();
    set.playTogether(animX, animY); // 同时执行缩放X和Y
    // 或者定义顺序:set.play(anim1).before(anim2).after(anim3);
    set.setDuration(500);
    set.start();
  4. 使用XML定义属性动画 在
    res/animator/
    目录下创建文件,例如
    animator_set.xml
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering="together">
        <objectAnimator
            android:propertyName="translationX"
            android:duration="1000"
            android:valueFrom="0"
            android:valueTo="200"
            android:valueType="floatType" />
    </set>

加载并应用XML属性动画:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.animator_set);
set.setTarget(imageView); // 设置动画作用的目标视图
set.start();

深入原理与难点解答

为什么补间动画的点击事件还在原位置?

补间动画(Tween Animation)的点击事件仍在视图初始位置触发,这源于其视觉与交互分离机制。

  • 视觉变化原理:补间动画通过父视图在绘制子视图时应用一个不断变化的
    Transformation
    (其中包含一个
    Matrix
    )来实现。这相当于给视图的“外表”加了一个特效,视图被画在了不同的位置,但其真实属性(如
    left
    ,
    top
    ,
    right
    ,
    bottom
    )从未改变。
  • 点击检测逻辑:Android系统在检测点击事件时,依据的是视图的实际占位区域(即其初始布局位置),而不是其绘制在屏幕上的视觉效果。因此,即使视图看起来移动了,系统仍认为它在老地方。

解决方案:若需在补间动画后使点击事件跟随视图,可在父视图的

onTouchEvent
中拦截点击事件,使用动画的变换矩阵进行逆向计算,判断点击是否落在视图当前显示区域内。但这种方法复杂, 更推荐使用属性动画从根本上解决问题。

为什么属性动画能改变属性?哪些属性不可改变?

属性动画(Property Animation)能够改变属性,是因为其核心设计是持续修改目标对象的属性值。

  • 工作机制:以
    ObjectAnimator
    为例,你需要告诉它要操作哪个对象的哪个属性(如
    View
    translationX
    )。动画过程中,系统会根据已播放的时间和设定的插值器,计算出一个当前值,然后自动调用该属性对应的 setter 方法(如
    setTranslationX(float)
    )来更新属性值。由于视图的属性被真实改变,其绘制位置和交互区域自然会更新。
  • 不可动画的属性:属性动画功能强大,但并非万能。以下几种情况的属性通常无法直接用于属性动画:
    • 没有对应的 Setter 方法:属性动画依赖于 setter 方法来更新属性。如果一个属性是
      final
      的(不可变)或只有 getter 方法而没有 setter 方法,则无法直接通过属性动画进行修改。
    • 属性变化无法触发界面更新:即使有 setter 方法,但如果设置新值后,无法以某种方式通知系统重绘视图(例如调用
      invalidate()
      方法),那么动画在屏幕上也看不到任何效果。
    • 线程不安全的属性:如果某个属性的 setter 方法非线程安全,而属性动画在后台线程更新其值,则可能导致并发问题。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Android DROID ROI Translation Background

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-2-19 10:53